Basic/B2a Example

It is equivalent to the B2a example in Geant4 but re-written with a new more Julia friendly interface. The core of the example is to create an instance of the type G4JLApplication with all the essential elements defined (detector and geometry, physics list, primary particles generator, actions, simulated data being accumulated, mapping of logical volumes to sensitive detectors, etc.)

Import the Geant4 and Geant4.SystemOfUnits modules

using Geant4
using Geant4.SystemOfUnits
using Printf, GeometryBasics

Define the Detector Parameters and Geometry

We include a file to define de structure B2aDetector and the construction method B2aConstruct to make the notebook more manageable

include(joinpath(@__DIR__, "DetectorB2a.jl"))

Define TrackerHit structure

struct TrackerHit
    trackID::Int32
    chamberNb::Int32
    edep::Float64
    pos::Point3{Float64}
end
function Base.show(io::IO, hit::TrackerHit)
    (;trackID, chamberNb, edep, pos) = hit
    @printf(io, "\ntrackID: %3d chamberNb: %2d Edep: %.3f MeV Position: (%3f, %3f, %3f)", trackID, chamberNb, edep/MeV, pos...) 
end

Define Sensitive Detector for the chambers

It implies to define a data structure where to accumulate the TrackerHits for each event, and the callback functions:

  • intilialize called at the beginning of each event
  • endOfEvent called at the end of the event
  • processHit called for each hit (step ending in the associated logical volume) to be processed

all of the callback functions get the declared data structure as first argument

#---SD collected data------------------------------------------------------------------------------
struct B2aSDData <: G4JLSDData
    trackerHits::Vector{TrackerHit}
    B2aSDData() = new([])
end
#---Initialize method------------------------------------------------------------------------------
function _initialize(::G4HCofThisEvent, data::B2aSDData)::Nothing
    empty!(data.trackerHits)
    return
end
#---End of Event method----------------------------------------------------------------------------
function _endOfEvent(::G4HCofThisEvent, data::B2aSDData)::Nothing
    return
end
#---Process Hit method-----------------------------------------------------------------------------
function _processHits(step::G4Step, ::G4TouchableHistory, data::B2aSDData)::Bool
    edep = step |> GetTotalEnergyDeposit
    edep <  0. && return false
    pos = step |> GetPostStepPoint |> GetPosition
    push!(data.trackerHits, TrackerHit(step |> GetTrack |> GetTrackID,
                                       step |> GetPreStepPoint |> GetTouchable |> GetCopyNumber,
                                       edep,
                                       Point3{Float64}(x(pos),y(pos),z(pos))))
    return true
end
_processHits (generic function with 1 method)

And create a specialized instance of G4JLSensitiveDetector

#---Create SD instance-----------------------------------------------------------------------------
chamber_SD = G4JLSensitiveDetector("Chamber_SD", B2aSDData();           # SD name an associated data are mandatory
                                    processhits_method=_processHits,    # process hist method (also mandatory)
                                    initialize_method=_initialize,      # intialize method
                                    endofevent_method=_endOfEvent);     # end of event method

Define an End Event Action

This is collect all results each event. Only printing at this time.

#---End Event Action-------------------------------------------------------------------------------
function endeventaction(evt::G4Event, app::G4JLApplication)
    hits = getSDdata(app, "Chamber_SD").trackerHits
    eventID = evt |> GetEventID
    if eventID < 10 || eventID % 100 == 0
      G4JL_println("Event: $eventID with $(length(hits)) hits stored in this event")
    end
    return
  end
endeventaction (generic function with 1 method)

Define the primary particle generator (Particle Gun)

particlegun = G4JLGunGenerator(particle = "proton", 
                               energy = 3GeV, 
                               direction = G4ThreeVector(0,0,1), 
                               position = G4ThreeVector(0,0,-2940.0))
G4JLGunGenerator("ParticleGun", Geant4.G4JLParticleGunData(nothing, "proton", G4ThreeVector(0.0,0.0,1.0), G4ThreeVector(0.0,0.0,-2940.0), 3000.0), Geant4.var"#init#19"(), Geant4.var"#gen#20"(), G4JLGeneratorAction[])

Instantiate a G4JLApplication with all the elements

The G4RunManager is created at this moment

#---Create the Application-------------------------------------------------------------------------
app = G4JLApplication( detector = B2aDetector(nChambers=5),          # detector with parameters
                       generator = particlegun,                      # primary particle generator
                       nthreads = 4,                                 # number of threads (MT)
                       physics_type = FTFP_BERT,                     # what physics list to instantiate
                       endeventaction_method = endeventaction,       # end event action
                       sdetectors = ["Chamber_LV+" => chamber_SD]    # mapping of LVs to SDs (+ means multiple LVs with same name)
                      );             
**************************************************************
 Geant4 version Name: geant4-11-02-patch-01 [MT]   (16-February-2024)
  << in Multi-threaded mode >> 
                       Copyright : Geant4 Collaboration
                      References : NIM A 506 (2003), 250-303
                                 : IEEE-TNS 53 (2006), 270-278
                                 : NIM A 835 (2016), 186-225
                             WWW : http://geant4.org/
**************************************************************

Final steps

Configure the application, initialize the run and fire the beam for 0 events to finalize all initializations

configure(app)
initialize(app)
Checking overlaps for volume Target:0 (G4Tubs) ... OK! 
Checking overlaps for volume Tracker:0 (G4Tubs) ... OK! 
Checking overlaps for volume Chamber_PV:1 (G4Tubs) ... OK! 
Checking overlaps for volume Chamber_PV:2 (G4Tubs) ... OK! 
Checking overlaps for volume Chamber_PV:3 (G4Tubs) ... OK! 
Checking overlaps for volume Chamber_PV:4 (G4Tubs) ... OK! 
Checking overlaps for volume Chamber_PV:5 (G4Tubs) ... OK!
beamOn(app, 0)
#---Forcing the loading of G4Vis extension------------------------------------------
using CairoMakie, Rotations, IGLWrap_jll  # to force loding G4Vis extension

world = GetWorldVolume()
img = draw(world)
display("image/png", img)

png

beamOn(app,10)
G4WT0 > Event: 2 with 112 hits stored in this event
G4WT3 > Event: 0 with 71 hits stored in this event
G4WT1 > Event: 3 with 160 hits stored in this event
G4WT0 > Event: 4 with 91 hits stored in this event
G4WT3 > Event: 5 with 80 hits stored in this event
G4WT2 > Event: 1 with 170 hits stored in this event
G4WT3 > Event: 8 with 61 hits stored in this event
G4WT0 > Event: 7 with 145 hits stored in this event
G4WT1 > Event: 6 with 117 hits stored in this event
G4WT2 > Event: 9 with 117 hits stored in this event
@time beamOn(app,1000)
G4WT2 > Event: 0 with 59 hits stored in this event
G4WT2 > Event: 1 with 89 hits stored in this event
G4WT2 > Event: 2 with 115 hits stored in this event
G4WT2 > Event: 3 with 650 hits stored in this event
G4WT2 > Event: 4 with 13 hits stored in this event
G4WT2 > Event: 5 with 497 hits stored in this event
G4WT2 > Event: 6 with 94 hits stored in this event
G4WT2 > Event: 7 with 76 hits stored in this event
G4WT2 > Event: 8 with 158 hits stored in this event
G4WT2 > Event: 9 with 87 hits stored in this event
G4WT3 > Event: 100 with 93 hits stored in this event
G4WT2 > Event: 200 with 225 hits stored in this event
G4WT2 > Event: 300 with 25 hits stored in this event
G4WT1 > Event: 400 with 54 hits stored in this event
G4WT0 > Event: 500 with 92 hits stored in this event
G4WT1 > Event: 600 with 70 hits stored in this event
G4WT1 > Event: 700 with 60 hits stored in this event
G4WT3 > Event: 800 with 75 hits stored in this event
G4WT2 > Event: 900 with 503 hits stored in this event
  0.997852 seconds (678.66 k allocations: 12.721 MiB)
SetParticleEnergy(particlegun, 500MeV)
@time beamOn(app,10000)
G4WT3 > Event: 0 with 224 hits stored in this event
G4WT2 > Event: 100 with 248 hits stored in this event
G4WT3 > Event: 1 with 294 hits stored in this event
G4WT3 > Event: 2 with 158 hits stored in this event
G4WT3 > Event: 3 with 8 hits stored in this event
G4WT3 > Event: 4 with 211 hits stored in this event
G4WT3 > Event: 5 with 199 hits stored in this event
G4WT3 > Event: 6 with 131 hits stored in this event
G4WT3 > Event: 7 with 174 hits stored in this event
G4WT3 > Event: 8 with 135 hits stored in this event
G4WT3 > Event: 9 with 143 hits stored in this event
G4WT2 > Event: 200 with 197 hits stored in this event
G4WT1 > Event: 300 with 239 hits stored in this event
G4WT2 > Event: 400 with 250 hits stored in this event
G4WT0 > Event: 500 with 181 hits stored in this event
G4WT2 > Event: 600 with 136 hits stored in this event
G4WT1 > Event: 700 with 175 hits stored in this event
G4WT2 > Event: 800 with 204 hits stored in this event
G4WT1 > Event: 900 with 244 hits stored in this event
G4WT3 > Event: 1000 with 246 hits stored in this event
G4WT1 > Event: 1100 with 155 hits stored in this event
G4WT2 > Event: 1200 with 198 hits stored in this event
G4WT1 > Event: 1300 with 209 hits stored in this event
G4WT2 > Event: 1400 with 142 hits stored in this event
G4WT1 > Event: 1500 with 224 hits stored in this event
G4WT2 > Event: 1600 with 151 hits stored in this event
G4WT0 > Event: 1700 with 152 hits stored in this event
G4WT2 > Event: 1800 with 145 hits stored in this event
G4WT1 > Event: 1900 with 193 hits stored in this event
G4WT2 > Event: 2000 with 256 hits stored in this event
G4WT1 > Event: 2100 with 217 hits stored in this event
G4WT2 > Event: 2200 with 141 hits stored in this event
G4WT0 > Event: 2300 with 171 hits stored in this event
G4WT2 > Event: 2400 with 137 hits stored in this event
G4WT0 > Event: 2500 with 212 hits stored in this event
G4WT2 > Event: 2600 with 111 hits stored in this event
G4WT0 > Event: 2700 with 126 hits stored in this event
G4WT2 > Event: 2800 with 0 hits stored in this event
G4WT0 > Event: 2900 with 0 hits stored in this event
G4WT3 > Event: 3000 with 205 hits stored in this event
G4WT1 > Event: 3100 with 180 hits stored in this event
G4WT0 > Event: 3200 with 152 hits stored in this event
G4WT3 > Event: 3300 with 171 hits stored in this event
G4WT0 > Event: 3400 with 156 hits stored in this event
G4WT3 > Event: 3500 with 124 hits stored in this event
G4WT1 > Event: 3600 with 200 hits stored in this event
G4WT3 > Event: 3700 with 163 hits stored in this event
G4WT1 > Event: 3800 with 483 hits stored in this event
G4WT0 > Event: 3900 with 139 hits stored in this event
G4WT1 > Event: 4000 with 10 hits stored in this event
G4WT0 > Event: 4100 with 28 hits stored in this event
G4WT1 > Event: 4200 with 165 hits stored in this event
G4WT2 > Event: 4300 with 132 hits stored in this event
G4WT1 > Event: 4400 with 142 hits stored in this event
G4WT0 > Event: 4500 with 223 hits stored in this event
G4WT1 > Event: 4600 with 147 hits stored in this event
G4WT0 > Event: 4700 with 142 hits stored in this event
G4WT1 > Event: 4800 with 152 hits stored in this event
G4WT3 > Event: 4900 with 153 hits stored in this event
G4WT1 > Event: 5000 with 162 hits stored in this event
G4WT3 > Event: 5100 with 176 hits stored in this event
G4WT1 > Event: 5200 with 320 hits stored in this event
G4WT2 > Event: 5300 with 155 hits stored in this event
G4WT3 > Event: 5400 with 175 hits stored in this event
G4WT2 > Event: 5500 with 171 hits stored in this event
G4WT0 > Event: 5600 with 147 hits stored in this event
G4WT1 > Event: 5700 with 3 hits stored in this event
G4WT0 > Event: 5800 with 145 hits stored in this event
G4WT1 > Event: 5900 with 156 hits stored in this event
G4WT0 > Event: 6000 with 212 hits stored in this event
G4WT1 > Event: 6100 with 8 hits stored in this event
G4WT0 > Event: 6200 with 277 hits stored in this event
G4WT1 > Event: 6300 with 0 hits stored in this event
G4WT0 > Event: 6400 with 227 hits stored in this event
G4WT3 > Event: 6500 with 208 hits stored in this event
G4WT2 > Event: 6600 with 104 hits stored in this event
G4WT0 > Event: 6700 with 200 hits stored in this event
G4WT2 > Event: 6800 with 4 hits stored in this event
G4WT0 > Event: 6900 with 153 hits stored in this event
G4WT2 > Event: 7000 with 166 hits stored in this event
G4WT0 > Event: 7100 with 141 hits stored in this event
G4WT2 > Event: 7200 with 182 hits stored in this event
G4WT0 > Event: 7300 with 140 hits stored in this event
G4WT2 > Event: 7400 with 249 hits stored in this event
G4WT1 > Event: 7500 with 8 hits stored in this event
G4WT2 > Event: 7600 with 233 hits stored in this event
G4WT3 > Event: 7700 with 155 hits stored in this event
G4WT2 > Event: 7800 with 0 hits stored in this event
G4WT1 > Event: 7900 with 201 hits stored in this event
G4WT2 > Event: 8000 with 8 hits stored in this event
G4WT1 > Event: 8100 with 161 hits stored in this event
G4WT2 > Event: 8200 with 143 hits stored in this event
G4WT3 > Event: 8300 with 3 hits stored in this event
G4WT2 > Event: 8400 with 170 hits stored in this event
G4WT0 > Event: 8500 with 186 hits stored in this event
G4WT2 > Event: 8600 with 146 hits stored in this event
G4WT3 > Event: 8700 with 142 hits stored in this event
G4WT0 > Event: 8800 with 177 hits stored in this event
G4WT1 > Event: 8900 with 192 hits stored in this event
G4WT0 > Event: 9000 with 115 hits stored in this event
G4WT2 > Event: 9100 with 119 hits stored in this event
G4WT0 > Event: 9200 with 156 hits stored in this event
G4WT2 > Event: 9300 with 3 hits stored in this event
G4WT0 > Event: 9400 with 155 hits stored in this event
G4WT1 > Event: 9500 with 132 hits stored in this event
G4WT0 > Event: 9600 with 144 hits stored in this event
G4WT2 > Event: 9700 with 270 hits stored in this event
G4WT3 > Event: 9800 with 1068 hits stored in this event
G4WT2 > Event: 9900 with 137 hits stored in this event
  5.464917 seconds (6.54 M allocations: 102.501 MiB)