3.4. Functions
Table of Contents
Defining functions
In Python, a function is a reusable block of code that performs a specific task. For GATE simulations, you will often wrap parts of your setup, such as geometry, sources, or actors, into functions so that your scripts become easier to read, test, and reuse.
You define a function with the keyword def, followed by a name, parentheses, and a colon. The code inside the function is indented. A very simple function looks like this:
def say_hello():
print("Hello from my GATE simulation!")
The name say_hello can be anything that follows Python naming rules. It should start with a letter or underscore, contain only letters, digits, or underscores, and should describe what the function does. For example, for GATE it is common to use names like create_world, add_sources, or configure_actors.
To run the code inside a function, you have to call it by using its name followed by parentheses:
say_hello()
In a GATE context, you might define a function that receives a simulation object and modifies it. Here is a simple example that assumes you already created a simulation object sim elsewhere:
def add_world(sim):
world = sim.world
world.size = [1.0, 1.0, 1.0]
world.material = "G4_AIR"This function does not create the simulation, it only configures the world volume. The function itself does not run the simulation, it prepares part of the setup. Separating these ideas keeps your main script short and clear.
Using functions gives you several advantages. You can reuse the same code to build similar scanners or phantoms, change parameters in one place instead of many, and test parts of your simulation in isolation. For a larger GATE project, you will naturally end up with many small, focused functions instead of a single long script.
Function parameters
Most useful functions need information from the outside world. In Python, this information is passed using parameters. Parameters are names inside the parentheses in the function definition. When you call the function, you give concrete values to these parameters, called arguments.
Here is a simple example that creates a box detector volume with a configurable size:
def add_box_detector(sim, name, size_xyz, material):
vol = sim.add_volume("Box", name)
vol.size = size_xyz
vol.material = material
In this definition, sim, name, size_xyz, and material are parameters. When you call the function, you supply arguments:
add_box_detector(
sim,
name="detector",
size_xyz=[5.0, 5.0, 2.0],
material="G4_WATER"
)These arguments can be passed by position or by name. Using names, as in the example above, often makes simulation scripts easier to read, especially when there are many parameters such as sizes, positions, energies, or activities.
You can also give parameters default values. This is very useful in GATE to define standard configurations, while still allowing overrides:
def add_water_box(sim, name="water_box", size_xyz=[10.0, 10.0, 10.0]):
vol = sim.add_volume("Box", name)
vol.size = size_xyz
vol.material = "G4_WATER"Now the function can be called with or without specifying all parameters:
# Uses default name and size
add_water_box(sim)
# Override only the size
add_water_box(sim, size_xyz=[20.0, 20.0, 5.0])You can also use keyword-only arguments to make scripts safer and more explicit. One simple pattern is to accept a dictionary of settings or require keywords for some parameters that you do not want to be passed by position:
def configure_source(sim, *, particle, energy_keV, activity_Bq):
src = sim.add_source("GenericSource", "src")
src.particle = particle
src.energy.mono = energy_keV
src.activity = activity_Bq
Here the * means that particle, energy_keV, and activity_Bq must be passed by name, not by position. This prevents confusion between energy and activity, which is especially important when both appear as numbers.
Working with parameters in this way lets you build flexible functions that describe scanner modules, beam lines, or dose scoring setups, and then reuse them in many different simulations simply by changing the arguments.
Return values
A function can send a result back to the caller using the return statement. This result is called the return value. If you do not explicitly return anything, Python returns None by default.
For GATE scripts, it is often useful to return created objects, such as volumes, sources, or actors, so that the calling code can further modify them if needed.
Here is a function that creates a box detector and returns it:
def create_box_detector(sim, name, size_xyz, material):
vol = sim.add_volume("Box", name)
vol.size = size_xyz
vol.material = material
return volYou can then call this function and store the returned volume:
det = create_box_detector(
sim,
name="detector",
size_xyz=[5.0, 5.0, 2.0],
material="G4_LYSO"
)
det.translation = [0.0, 0.0, 10.0]The function hides the repetitive creation steps, and the calling code focuses on high level configuration.
A function can also return more than one value. Internally, Python packs them into a tuple. This is useful when one function sets up several related parts of a simulation, such as a source and an actor:
def create_source_and_dose_actor(sim, activity_Bq):
src = sim.add_source("GenericSource", "src")
src.particle = "gamma"
src.activity = activity_Bq
dose = sim.add_actor("DoseActor", "dose")
dose.output = "dose.mhd"
return src, doseYou can receive these results in separate variables:
source, dose_actor = create_source_and_dose_actor(sim, activity_Bq=1e6)Sometimes you do not need to return anything. In that case, the function simply modifies the objects you pass in. This is common for configuration functions:
def configure_pet_physics(sim):
sim.physics_list = "G4EmStandardPhysics"Such functions are still very useful because they keep your main script readable.
In mathematical contexts, you may work with functions that return numbers or arrays. For example, you could compute a simple analytical attenuation factor using the exponential law:
import math
def attenuation_factor(mu, thickness_cm):
return math.exp(-mu * thickness_cm)You could then compare this result with simulated transmission from GATE.
Important rule: A function stops executing as soon as a return statement is reached. Any code written after return in the same block will not run.
By defining clear return values, you make your GATE simulation code modular and predictable. Each function answers a single question or performs a specific setup step, and the returned values make the flow of data through your simulation explicit.
Views: 11
KAHIBARO