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") let = ((d1 * l1) + (d2 * l2)) / (d1 + d2) let.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 40 41 42 43 44 | """ This example shows how to use contours to select volume of interests inside a CTX cube. The VOI is then manipulated. """ import logging import pytrip as pt # by default logging in PyTRiP98 is disabled, here we enable it to see it with basic INFO level logging.basicConfig(level=logging.DEBUG) # 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.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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | """ 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. """ import os import logging import pytrip as pt import pytrip.tripexecuter as pte logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) # give some output on what is going on. # Please adjust these paths according to location of the patient data (CT and contouring) and TRiP98 installation. # Fist we specify the directory where all our files are: wdir = "/home/user/workspace" # working dir must exist. patient_dir = "/home/user/data/yoda" trip_path = "/home/user/usr/trip98" # In TRiP, the patient "TST000" would typically carry the filename "TST000000" patient_name = "TST000000" # so we can construc the paths to the CTX and VDX files like this: ctx_path = os.path.join(patient_dir, patient_name + ".ctx") vdx_path = os.path.join(patient_dir, patient_name + ".vdx") # Next we load the CT cube: c = pt.CtxCube() c.read(ctx_path) # And load the contours v = pt.VdxCube(c) v.read(vdx_path) # we may print all contours found in the Vdx file, if we want to print(v.voi_names()) # We need to specify where the kernel files can be found. The location may depend on the ion we # want to treat with. This example sets up a kernel model for C-12 ions with a 3 mm Ripple Filter. mykernel = pte.KernelModel() mykernel.projectile = pte.Projectile("C", a=12) mykernel.ddd_path = trip_path + "/DATA/DDD/12C/RF3MM/*" mykernel.spc_path = trip_path + "/DATA/SPC/12C/RF3MM/*" mykernel.sis_path = trip_path + "/DATA/SIS/19981218.sis" mykernel.rifi_thickness = 3.0 # 3 mm ripple filter. (Only for documentaiton, will not affect dose optimization.) mykernel.rifi_name = "GSI_1D_3mm" # Additional free text for documentation. mykernel.comment = "Carbon-12 ions with 3 mm 1D Ripple Filter" # Ok, we have the Contours, the CT cube and dose kernels ready. Next we must prepare a plan. # We may choose any basename for the patient. All output files will be named using # this basename. plan = pte.Plan(basename=patient_name, default_kernel=mykernel) # Plan specific data: plan.hlut_path = trip_path + "/DATA/HLUT/19990218.hlut" # Hounsfield lookup table location plan.dedx_path = trip_path + "/DATA/DEDX/20000830.dedx" # Stopping power tables plan.working_dir = wdir # Set the plan target to the voi called "CTV" plan.voi_target = v.get_voi_by_name('CTV') # some optional plan specific parameters (if not set, they will all be zero by default) plan.bolus = 0.0 # No bolus is applied here. Set this to some value, if you are to optimize very shallow tumours. plan.offh2o = 1.873 # Some offset mimicing the monitoring ionization chambers and exit window of the beam nozzle. # Next we need to specify at least one field, and add that field to the plan. field = pte.Field(kernel=mykernel) # The ion speicies is selected by passing the corresponding kernel to the field. field.basename = patient_name # This name will be used for output filenames, if any field specific output is saved. field.gantry = 10.0 # degrees field.couch = 90.0 # degrees field.fwhm = 4.0 # spot size in [mm] print(field) # We can print all parameters of this field, for checking. plan.fields.append(field) # attach field to plan. You may attach multiple fields. # Next, set the flags for what output should be generated, when the plan has completed. plan.want_phys_dose = True # We want a physical dose cube, "TST000000.dos" plan.want_bio_dose = False # No biological cube (Dose * RBE) plan.want_dlet = True # We want to have the dose-averaged LET cube plan.want_rst = False # Print the raster scan files (.rst) for all fields. # print(plan) # this will print all plan parameters te = pte.Execute(c, v) # get the executer object, based on the given Ctx and Vdx cube. # in the case that TRiP98 is not installed locally, you may have to enable remote execution: # te.remote = True # te.servername = "titan.phys.au.dk" # te.username = "bassler" # te.password = "xxxxxxxx" # you can set a password, but this is strongly discouraged. Better to exchange SSH keys! # te.remote_base_dir = "/home/bassler/test" # # Depending on the remote .bashrc_profile setup, it may be needed to specify the full path # for the remote TRiP installation. On some systems the $PATH is set, so this line can be omitted, # or shortened to just "TRiP98" : # te.trip_bin_path = trip_path + "/bin/TRiP98" te.execute(plan) # this will run TRiP # te.execute(plan, False) # set to False, if TRiP98 should not be executed. Good for testing. # requested results can be found in # plan.dosecubes[] # and # plan.letcubes[] # and they are also saved to working_dir |