# TOPAS Time Feature Example to paint a moving target with a scanning beam.
# This is the completed form of the example, after all steps have been completed.
# Sometimes a later step required commenting out a line from an earlier step
# (to avoid setting the same parameter twice in this same file).
# So if you're taking just a subset of this example, you may need to uncomment
# some of the lines.
# Step 1: Create a simple target and visualize it
# Create the Target as a box of water, 260 cm in X and Y, 2 cm total depth.
# Place this into the world translated 200 cm from center in Z.
s:Ge/Target/Type = "TsBox"
s:Ge/Target/Parent = "World"
s:Ge/Target/Material = "G4_WATER"
d:Ge/Target/HLX = 130. cm
d:Ge/Target/HLY = 130. cm
d:Ge/Target/HLZ = 1. cm
d:Ge/Target/TransZ = -200. cm
# Create an OpenGL graphics view with rotations of 70 deg Theta and
# 10 deg Phi and zoom factor of 5.
# You will notice the Theta line commented out here because we set it differently
# at a later step. If you're just running this step, uncomment this line.
s:Gr/MyView/Type = "OpenGL"
#d:Gr/MyView/Theta = 70. deg
d:Gr/MyView/Phi = 10. deg
u:Gr/MyView/Zoom = 5
# For particle source, use the built-in demonstration source.
# Set it to make 200 histories per run.
i:So/Demo/NumberOfHistoriesInRun = 200
Ts/ShowHistoryCountAtInterval = 100
# Turn on PauseBeforeQuit so we have a chance to see the graphics.
b:Ts/PauseBeforeQuit = "True"
# Run. You should see 50 particle histories.
# Most of the created particles should hit the center of the target.
# MacOS 10.15 users will find that the Qt GUI starts up automatically.
# To generate particles, hit the Run button above the parameter control widget.
# Step 2: Make the simulation start faster
# Simplify the physics so that the simulation starts faster.
sv:Ph/Default/Modules = 1 "g4em-standard_opt0"
# Run. You should see that the simulation starts very fast.
# This happens at the expense of losing scattering accuracy and losing
# all hadronic physics.
# Remember to change back to full physics if you need high accuracy.
# Step 3: Improve the visualization
# Make the target solid.
s:Ge/Target/DrawingStyle = "Solid"
# Make trajectories disappear when they enter this solid.
b:Gr/MyView/HiddenLineRemovalForTrajectories = "True"
# Run. You should see a solid target and trajectories disappear into the target.
# Step 4: Simplify further by removing most of the scatter from the simulation
# and removing random variation in the beam model.
# Change World material to Vacuum
s:Ge/World/Material = "Vacuum"
# Change Beam to have no energy spread (BeamEnergySpread).
u:So/Demo/BeamEnergySpread = 0.
# Change Beam's initial profile to be 4.cm radius (BeamPositionCutoffX and Y).
d:So/Demo/BeamPositionCutoffX = 4. cm
d:So/Demo/BeamPositionCutoffY = 4. cm
# Change Beam's distribution within this profile to be flat
# (BeamPositionDistribution to Flat rather than Gaussian).
s:So/Demo/BeamPositionDistribution = "Flat"
# Turn off angular divergence of the beam (BeamAngularDistribution to None).
s:So/Demo/BeamAngularDistribution = "None"
# Run. You should no longer see delta rays produced in the air.
# There may still be a rare scatter, as Geant4, like nature,
# does not have the concept of an absolutely perfect vacuum.
# The beam should now be distributed in a uniform circular profile.
# Step 5: Create the components that will become our two bending magnets
# Create a Group Component that will represent our scanning nozzle.
# Place this into the World offset 100 cm to the left.
s:Ge/Nozzle/Type = "Group"
s:Ge/Nozzle/Parent = "World"
d:Ge/Nozzle/TransZ = 100. cm
# Make two cylinders of vacuum, one just before center of the Nozzle, one just after.
# Make each of them 20cm total length, 30 cm radius.
s:Ge/BendingMagnetX/Type = "TsCylinder"
s:Ge/BendingMagnetX/Parent = "Nozzle"
s:Ge/BendingMagnetX/Material = "Vacuum"
d:Ge/BendingMagnetX/HL = 40. cm
dc:Ge/BendingMagnetX/RMax = 30. cm
d:Ge/BendingMagnetX/TransZ = Ge/BendingMagnetX/HL cm
s:Ge/BendingMagnetY/Type = "TsCylinder"
s:Ge/BendingMagnetY/Parent = "Nozzle"
s:Ge/BendingMagnetY/Material = "Vacuum"
d:Ge/BendingMagnetY/HL = 40. cm
dc:Ge/BendingMagnetY/RMax = 70. cm
d:Ge/BendingMagnetY/TransZ = -1. * Ge/BendingMagnetY/HL cm
# Run. Notice that it's hard to tell the magnets apart as they are the same color.
# Since we have not specified color, the color was based on the material.
# since they are both Vacuum, they came out the same color.
# Step 6: Color the X magnet Red and the Y magnet Yellow
s:Ge/BendingMagnetX/Color = "Red"
s:Ge/BendingMagnetY/Color = "Yellow"
# Run. You should see that the bending mangets now each have their own color.
# Step 7: Give each magnet a dipole magnetic field
# Make each magnet have the appropriate field direction cosines.
# Set the X bending magnet to -.8 tesla and the X bending magnet to -1. tesla.
# Make the field strength be a Changeable parameter (use "dc:" instead of "d:").
s:Ge/BendingMagnetX/Field = "DipoleMagnet"
u:Ge/BendingMagnetX/MagneticFieldDirectionX = 0.0
u:Ge/BendingMagnetX/MagneticFieldDirectionY = 1.0
u:Ge/BendingMagnetX/MagneticFieldDirectionZ = 0.0
#dc:Ge/BendingMagnetX/MagneticFieldStrength = -.8 tesla
s:Ge/BendingMagnetY/Field = "DipoleMagnet"
u:Ge/BendingMagnetY/MagneticFieldDirectionX = 1.0
u:Ge/BendingMagnetY/MagneticFieldDirectionY = 0.0
u:Ge/BendingMagnetY/MagneticFieldDirectionZ = 0.0
#dc:Ge/BendingMagnetY/MagneticFieldStrength = -1. tesla
# Turn on the Qt GUI
# MacOS 10.15 users do not need to do this since on that system the
# Qt GUI starts up automatically.
# To generate particles, hit the Run button above the parameter control widget.
#b:Ts/UseQt = "True"
# You should see that the beam has been bent in both the X and Y direction.
# Study the effect of various magnetic field strengths by adjusting the
# field strengths in the GUI and hitting the GUI's run button after each change.
# The combination of these two fields controls where the beam hits the target.
# Step 8: Make a time feature control the strength of BendingMagnetX
# Create a time feature that creates an increasing magnetic field.
s:Tf/XFieldIncreasing/Function = "Linear tesla"
d:Tf/XFieldIncreasing/Rate = 0.16 tesla/ms
d:Tf/XFieldIncreasing/StartValue = -.8 tesla
d:Tf/XFieldIncreasing/RepetitionInterval = 11.0 ms
# Use this time feature to control the X magnet.
#d:Ge/BendingMagnetX/MagneticFieldStrength = Tf/XFieldIncreasing/Value tesla
# Declare that the simulation should contain 11 runs.
i:Tf/NumberOfSequentialTimes = 110
# Specify an end time for the run sequence.
d:Tf/TimelineEnd = 110. ms
# Set verbosity to get more information about the runs.
i:Tf/Verbosity = 2
# Run. You should see that the beam sweeps from left to right and the repeats.
# Step 9: Make the scan go the opposite direction
# Create a time feature that creates a decreasing magnetic field.
s:Tf/XFieldDecreasing/Function = "Linear tesla"
d:Tf/XFieldDecreasing/Rate = -0.16 tesla/ms
d:Tf/XFieldDecreasing/StartValue = .8 tesla
d:Tf/XFieldDecreasing/RepetitionInterval = 11.0 ms
# Use this time feature to control the X magnet.
#d:Ge/BendingMagnetX/MagneticFieldStrength = Tf/XFieldDecreasing/Value tesla
# Run. You should see that the beam sweeps from right to left and the repeats.
# Step 10: Use a Step time feature to make the scan alternate directions
# Use a Step function and have the value come first from
# Tf/XFieldIncreasing/Value and then from Tf/XFieldIncreasing/Value.
s:Tf/XFieldAlternating/Function = "Step"
dv:Tf/XFieldAlternating/Times = 2 11. 22. ms
dv:Tf/XFieldAlternating/Values = 2 Tf/XFieldIncreasing/Value Tf/XFieldDecreasing/Value tesla
# Use this time feature to control the X magnet
#d:Ge/BendingMagnetX/MagneticFieldStrength = Tf/XFieldAlternating/Value tesla
# Run. You should see that the beam sweeps back and forth.
# It is alternately being driven by Tf/XFieldIncreasing and Tf/XFieldDecreasing.
# Step 11: Complete the raster scan pattern by controlling the Y magnet
# Create a field that increases every 11 ms (each time the X scan is completed).
s:Tf/YFieldDecreasing/Function = "Step"
dv:Tf/YFieldDecreasing/Times = 10 11. 22. 33. 44. 55. 66. 77. 88. 99. 110. ms
dv:Tf/YFieldDecreasing/Values = 10 -1. -.8 -.6 -.4 -.2 0. .2 .4 .6 .8 tesla
# Use this time feature to control the Y magnet.
d:Ge/BendingMagnetY/MagneticFieldStrength = Tf/YFieldDecreasing/Value tesla
# Run. You should see that the beam moves downward at the end of each
# horizontal sweep. This combination of horizontal and vertical scanning is
# called "raster scanning."
# Step 12: Simulate patient motion by making the target move horizontally
# in a sinusoidal motion
# Use a Sine function time feature.
s:Tf/HorizontalMoveSine/Function = "Sine"
d:Tf/HorizontalMoveSine/RepetitionInterval = 110. ms
d:Tf/HorizontalMoveSine/Rate = 6. deg/ms
d:Tf/HorizontalMoveSine/StartValue = -90. deg
# Use this time feature to control the Target
dc:Ge/Target/TransX = 100.0 cm * Tf/HorizontalMoveSine/Value
# Adjust the graphics view so it is easier to see the target motion.
d:Gr/MyView/Theta = 20. deg
# Run. You will see that the beam is sometimes missing the target.
# Step 13: Make the beam compensate to stay on the target
# Create a new parameter to hold amplitude of necessary beam magnet adjustment.
d:FieldAdjustment = .6 tesla * Tf/HorizontalMoveSine/Value
# Add this adjustment to the value that was controlling the simple X scan.
d:Ge/BendingMagnetX/MagneticFieldStrength = Tf/XFieldAlternating/Value + FieldAdjustment tesla
# As an additional diagnostic, ask for parameters to be printed out at each run:
b:Ts/DumpNonDefaultParameters = "True"
# Run. You will see that the raster scan now stays on the target as the target moves.