Examples

Code snippets demonstrating PyTRiP capabilities.

Example 00 - Cube arithmetic

This example demonstrates simple arithmetic on dose- and LET-cubes. Two dose cubes from two fields are summed to generate a new total dose cube.

The two LET-cubes from the two fields are combined to calculate the total dose-averaged LET in the resulting treatment plan. All data are saved to disk.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"""
Simple example of how to do arithmetic on Cube objects in PyTRiP.
"""
import pytrip as pt

# sum two dose cubes, write result:
print("Two half boxes: out.dos")
d1 = pt.DosCube()
d2 = pt.DosCube()
d1.read("box052000.dos")
d2.read("box053000.dos")
d = (d1 + d2)
d.write("out.dos")

# print minium and maximum value found in cubes
print(d1.cube.min(), d1.cube.max())
print(d2.cube.min(), d2.cube.max())

# calculate new dose average LET cube
l1 = pt.LETCube()
l2 = pt.LETCube()
l1.read("box052000.dosemlet.dos")
l2.read("box053000.dosemlet.dos")

l = ((d1 * l1) + (d2 * l2)) / (d1 + d2)
l.write("out.dosemlet.dos")

Example 01 - Handling structures

This example shows how one can select a region inside a CTX data cube using a VDX file, and perform some manipulation of it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"""
This example shows how to use contours to select volume of interests inside a CTX cube. The VOI is then manipulated.
"""
import pytrip as pt

# first define some paths and other important parameters
ctx_path = "/home/bassler/Projects/CTdata/TST000/TST000000.ctx"
vdx_path = "/home/bassler/Projects/CTdata/TST000/TST000000.vdx"
my_target_voi = "GTV"

# load CT cube
my_ctx = pt.CtxCube()
my_ctx.read(ctx_path)

# load VOIs
my_vdx = pt.VdxCube(my_ctx)  # my_vdx is the object which will hold all volumes of interest and the meta information
my_vdx.read(vdx_path)  # load the .vdx file
print(my_vdx.get_voi_names())  # show us all VOIs found in the .vdx file

# Select the requested VOI from the VdxCube object
target_voi = my_vdx.get_voi_by_name(my_target_voi)

# get_voi_cube() returns a DosCube() object, where all voxels inside the VOI holds the value 1000, and 0 elsewhere.
voi_cube = target_voi.get_voi_cube()

# Based on the retrieved DosCube() we calculate a three dimensional mask object,
# which assigns True to all voxels inside the Voi, and False elsewhere.
mask = (voi_cube.cube == 1000)

# "The mask object and the CTX cube have same dimensions (they are infact inherited from the same top level class).
# Therefore we can apply the mask cube to the ctx cube and work with the values.
# For instance we can set all HUs to zero within the Voi:
my_ctx.cube[mask] = 0
# or add 100 to all HUs of the voxels inside the mask:
# my_ctx.cube[mask] += 100

# save masked CT to the file in current directory
masked_ctx = "masked.ctx"
my_ctx.write(masked_ctx)

Working with dose cubes is fully analogous to the CTX cubes.

Example 02 - TRiP execution

In this example, we demonstrate how to actually perform a treatment plan using TRiP98. Most of the lines concern with the setup of TRiP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""
This example demonstrates how to load a CT cube in Voxelplan format, and the associated contours.
Then a plan is prepared and optimized using TRiP98.
The resulting dose plan is then stored in <some_dir>.
"""

import pytrip as pt
import pytrip.tripexecuter as pte

# first define some paths and other important parameters
patient_name = "TST000000"
ctx_path = "/home/bassler/Projects/CTdata/TST000/TST000000.ctx"
vdx_path = "/home/bassler/Projects/CTdata/TST000/TST000000.vdx"
voi_name = "GTV"
working_directory = "/home/bassler/Projects/CTdata/TST000/"

ddd_dir = "/home/bassler/TRiP98/base/DATA/DDD/12C/RF3MM"
spc_dir = "/home/bassler/TRiP98/base/DATA/SPC/12C/RF3MM"
sis_path = "/home/bassler/TRiP98/base/DATA/SIS/12C.sis"
hlut_path = "/home/bassler/TRiP98/base/DATA/HLUT/19990218.hlut"
dedx_path = "/home/bassler/TRiP98/base/DATA/DEDX/20040607.dedx"

my_couch_angle = 90.0
my_gantry_angle = 10.0
my_target_voi = "GTV"  # the name must exist in the .vdx file
my_projectile = "C"  # carbon ion

# load CT cube
my_ctx = pt.CtxCube()
my_ctx.read(ctx_path)

# load VOIs
my_vdx = pt.VdxCube(my_ctx)  # my_vdx is the object which will hold all volumes of interest and the meta information
my_vdx.read(vdx_path)  # load the .vdx file
print(my_vdx.get_voi_names())  # show us all VOIs found in the .vdx file

# next pick a the proper VOI (from the VdxCube object) which we want to plan on
target_voi_temp = my_vdx.get_voi_by_name(my_target_voi)

# for technical reasons the voi must be cast into a new Voi object
# we are working on a cleaner Voi class implementation to avoid it
target_voi = pte.Voi("GTV_VOI", target_voi_temp)

# Next, setup a plan. We may initialize it with a new name.
# The name must be identical to the base name of the file, else we will have crash
my_plan = pte.TripPlan(name=patient_name)

# set working directory, output will go there
my_plan.set_working_dir(working_directory)
my_plan.set_ddd_folder(ddd_dir)
my_plan.set_spc_folder(spc_dir)
my_plan.set_dedx_file(dedx_path)
my_plan.set_hlut_file(hlut_path)
my_plan.set_sis_file(sis_path)

# To enable remote access to trip, uncomment and eddit the following:
# my_plan.set_remote_state(True)
# my_plan.set_server("titan.phys.au.dk")  # location of remote TRiP98 installation. Needs SSH access.
# my_plan.set_username("xxxxxxxxx")
# my_plan.set_password("xxxxxxxxx")  # to login using SSH-keys, leave this commented out.

# add target VOI to the plan
my_plan.add_voi(target_voi)
my_plan.get_vois()[0].target = True  # make TRiP98 aware of that this VOI is the target.

# Finally we need to add a field to the plan
# add default field, carbon ions
my_field = pte.Field("Field 1")
my_field.set_projectile(my_projectile)  # set the projectile
my_field.set_couch(my_couch_angle)
my_field.set_gantry(my_gantry_angle)

my_plan.add_field(my_field)

# the next line is needed to correctly set offset between VOI and CT
ct_images = pt.CTImages(my_ctx)

# run TRiP98 optimisation
my_trip = pte.TripExecuter(ct_images.get_modified_images(my_plan))
# TRiP98 will then run the plan and generate the requested dose plan.
# The dose plan is stored in the working directory, and must then be loaded by the user for further processing.
# for local execution, we assume TRiP98 binary is present in PATH env. variable
my_trip.execute(my_plan)