33 This example shows creating and modification of wavelet bases for fluence map compression using portpy
44
55"""
6+ # import sys
7+ # sys.path.append('..')
68import portpy .photon as pp
79from low_dim_rt import LowDimRT
810import numpy as np
1315def ex_wavelet ():
1416 # specify the patient data location
1517 # you first need to download the patient database from the link provided in the PortPy GitHub page
16- data_dir = r'F:\Research\Data_newformat\Python-PORT \data'
18+ data_dir = r'. \data'
1719 # pick a patient from the existing patient list to get detailed info about the patient data (e.g., beams_dict, structures, ...)
1820 patient_id = 'Lung_Patient_2'
1921 # create my_plan object for the planner beams_dict and select among the beams which are 30 degrees apart
@@ -34,70 +36,75 @@ def ex_wavelet():
3436 'max_dose_gy' : rind_max_dose [4 ]}]
3537 my_plan .add_rinds (rind_params = rind_params )
3638
37- # create cvxpy problem using the clinical criteria
38- prob = pp .CvxPyProb (my_plan , opt_params = {'smoothness_weight' : 10 })
39-
40- # run imrt fluence map optimization using cvxpy and one of the supported solvers and save the optimal solution in sol
41- # CVXPy supports several opensource (ECOS, OSQP, SCS) and commercial solvers (e.g., MOSEK, GUROBI, CPLEX)
42- # For optimization problems with non-linear objective and/or constraints, MOSEK often performs well
43- # For mixed integer programs, GUROBI/CPLEX are good choices
44- # If you have .edu email address, you can get free academic license for commercial solvers
45- # we recommend the commercial solver MOSEK as your solver for the problems in this example,
46- # however, if you don't have a license, you can try opensource/free solver SCS or ECOS
47- # see https://www.cvxpy.org/tutorial/advanced/index.html for more info about CVXPy solvers
48- # To set up mosek solver, you can get mosek license file using edu account and place the license file in directory C:\Users\username\mosek
49- prob .solve (solver = 'MOSEK' , verbose = True )
50- sol = prob .get_sol ()
39+ # With no quadratic smoothness
40+ prob = pp .CvxPyProb (my_plan , smoothness_weight = 0 )
41+ prob .solve (solver = 'MOSEK' , verbose = False )
42+ sol_no_quad_no_wav = prob .get_sol ()
5143
52- # run IMRT fluence map optimization using a low dimensional subspace for fluence map compression
53- prob = pp .CvxPyProb (my_plan , opt_params = {'smoothness_weight' : 10 })
5444 # creating the wavelet incomplete basis representing a low dimensional subspace for dimension reduction
5545 wavelet_basis = LowDimRT .get_low_dim_basis (my_plan .inf_matrix , 'wavelet' )
5646 # Smoothness Constraint
5747 y = cp .Variable (wavelet_basis .shape [1 ])
5848 prob .constraints += [wavelet_basis @ y == prob .x ]
5949 prob .solve (solver = 'MOSEK' , verbose = False )
60- sol_low_dim = prob .get_sol ()
50+ sol_no_quad_with_wav = prob .get_sol ()
51+
52+ # create cvxpy problem using the clinical criteria
53+ prob = pp .CvxPyProb (my_plan , smoothness_weight = 10 )
54+ # run IMRT fluence map optimization using a low dimensional subspace for fluence map compression
55+ prob .solve (solver = 'MOSEK' , verbose = False )
56+ sol_quad_no_wav = prob .get_sol ()
6157
62- # With no quadratic smoothness
63- prob = pp .CvxPyProb (my_plan , opt_params = {'smoothness_weight' : 0 })
64- # creating the wavelet incomplete basis representing a low dimensional subspace for dimension reduction
65- wavelet_basis = LowDimRT .get_low_dim_basis (my_plan .inf_matrix , 'wavelet' )
6658 # Smoothness Constraint
6759 y = cp .Variable (wavelet_basis .shape [1 ])
6860 prob .constraints += [wavelet_basis @ y == prob .x ]
6961 prob .solve (solver = 'MOSEK' , verbose = False )
70- sol_low_dim_only = prob .get_sol ()
62+ sol_quad_with_wav = prob .get_sol ()
63+
64+ pp .save_plan (my_plan , plan_name = 'my_plan' , path = r'C:\temp' )
65+ pp .save_optimal_sol (sol_no_quad_no_wav , sol_name = 'sol_no_quad_no_wav' , path = r'C:\temp' )
66+ pp .save_optimal_sol (sol_no_quad_with_wav , sol_name = 'sol_no_quad_with_wav' , path = r'C:\temp' )
67+ pp .save_optimal_sol (sol_quad_no_wav , sol_name = 'sol_quad_no_wav' , path = r'C:\temp' )
68+ pp .save_optimal_sol (sol_quad_with_wav , sol_name = 'sol_quad_with_wav' , path = r'C:\temp' )
69+
70+ # my_plan = pp.load_plan(plan_name='my_plan', path=r'C:\temp')
71+ # sol_no_quad_no_wav = pp.load_optimal_sol(sol_name='sol_no_quad_no_wav', path=r'C:\temp')
72+ # sol_no_quad_with_wav = pp.load_optimal_sol(sol_name='sol_no_quad_with_wav', path=r'C:\temp')
73+ # sol_quad_no_wav = pp.load_optimal_sol(sol_name='sol_quad_no_wav', path=r'C:\temp')
74+ # sol_quad_with_wav = pp.load_optimal_sol(sol_name='sol_quad_with_wav', path=r'C:\temp')
7175
7276 # plot fluence 3D and 2D
73- fig , ax = plt .subplots (1 , 3 , figsize = (12 , 12 ), subplot_kw = {'projection' : '3d' })
74- pp .Visualize .plot_fluence_3d (sol = sol , beam_id = 0 , ax = ax [0 ])
75- pp .Visualize .plot_fluence_3d (sol = sol_low_dim , beam_id = 0 , ax = ax [1 ])
76- pp .Visualize .plot_fluence_3d (sol = sol_low_dim_only , beam_id = 0 , ax = ax [2 ])
77- plt .show ()
77+ fig , ax = plt .subplots (1 , 2 , figsize = (18 , 6 ), subplot_kw = {'projection' : '3d' })
78+ fig .suptitle ('Without Quadratic smoothness' )
79+ pp .Visualize .plot_fluence_3d (sol = sol_no_quad_no_wav , beam_id = 37 , ax = ax [0 ], title = 'Without Wavelet' )
80+ pp .Visualize .plot_fluence_3d (sol = sol_no_quad_with_wav , beam_id = 37 , ax = ax [1 ], title = 'With Wavelet' )
7881
79- fig , ax = plt .subplots (1 , 3 , figsize = (12 , 12 ) )
80- pp . Visualize . plot_fluence_2d ( sol = sol , beam_id = 0 , ax = ax [ 0 ] )
81- pp .Visualize .plot_fluence_2d (sol = sol_low_dim , beam_id = 0 , ax = ax [1 ] )
82- pp .Visualize .plot_fluence_2d (sol = sol_low_dim_only , beam_id = 0 , ax = ax [2 ] )
82+ fig , ax = plt .subplots (1 , 2 , figsize = (18 , 6 ), subplot_kw = { 'projection' : '3d' } )
83+ fig . suptitle ( 'With Quadratic smoothness' )
84+ pp .Visualize .plot_fluence_3d (sol = sol_quad_no_wav , beam_id = 37 , ax = ax [0 ], title = 'Without Wavelet' )
85+ pp .Visualize .plot_fluence_3d (sol = sol_quad_with_wav , beam_id = 37 , ax = ax [1 ], title = 'With Wavelet' )
8386 plt .show ()
87+
8488 # plot DVH for the structures in the given list. Default dose_1d is in Gy and volume is in relative scale(%).
85- structs = ['PTV' , 'ESOPHAGUS' , 'HEART' , 'CORD' ]
86- fig , ax = plt .subplots (figsize = (12 , 12 ))
87- ax = pp .Visualize .plot_dvh (my_plan , sol = sol , structs = structs , ax = ax )
88- ax = pp .Visualize .plot_dvh (my_plan , sol = sol_low_dim , structs = structs , ax = ax )
89- pp .Visualize .plot_dvh (my_plan , sol = sol_low_dim_only , structs = structs , ax = ax )
90- plt .show ()
91- # plot 2d axial slice for the given solution and display the structures contours on the slice
92- fig , ax = plt .subplots (1 , 3 , figsize = (12 , 12 ))
93- pp .Visualize .plot_2d_dose (my_plan , sol = sol , slice_num = 40 , structs = ['PTV' ], ax = ax [0 ])
94- pp .Visualize .plot_2d_dose (my_plan , sol = sol_low_dim , slice_num = 40 , structs = ['PTV' ], ax = ax [1 ])
95- pp .Visualize .plot_2d_dose (my_plan , sol = sol_low_dim_only , slice_num = 40 , structs = ['PTV' ], ax = ax [2 ])
89+ structs = ['PTV' , 'ESOPHAGUS' , 'HEART' , 'CORD' , 'LUNG_L' , 'LUNG_R' ]
90+ fig , ax = plt .subplots (1 , 2 , figsize = (20 , 8 ))
91+ ax0 = pp .Visualize .plot_dvh (my_plan , sol = sol_no_quad_no_wav , structs = structs , style = 'solid' , ax = ax [0 ])
92+ ax0 = pp .Visualize .plot_dvh (my_plan , sol = sol_no_quad_with_wav , structs = structs , style = 'dashed' , ax = ax0 )
93+ fig .suptitle ('DVH comparison' )
94+ ax0 .set_title ('Without Quadratic smoothness \n solid: Without Wavelet, Dash: With Wavelet' )
95+ # plt.show()
96+ # print('\n\n')
97+
98+ # fig, ax = plt.subplots(figsize=(12, 8))
99+ ax1 = pp .Visualize .plot_dvh (my_plan , sol = sol_quad_no_wav , structs = structs , style = 'solid' , ax = ax [1 ])
100+ ax1 = pp .Visualize .plot_dvh (my_plan , sol = sol_quad_with_wav , structs = structs , style = 'dashed' , ax = ax1 )
101+ ax1 .set_title ('With Quadratic smoothness \n solid: Without Wavelet, Dash: With Wavelet' )
96102 plt .show ()
103+
97104 # visualize plan metrics based upon clinical criteria
98- pp .Visualize .plan_metrics (my_plan , sol = sol )
99- pp . Visualize . plan_metrics ( my_plan , sol = sol_low_dim )
100- pp . Visualize . plan_metrics ( my_plan , sol = sol_low_dim_only )
105+ pp .Visualize .plan_metrics (my_plan ,
106+ sol = [ sol_no_quad_no_wav , sol_no_quad_with_wav , sol_quad_no_wav , sol_quad_with_wav ],
107+ sol_names = [ 'no_quad_no_wav' , 'no_quad_with_wav' , 'quad_no_wav' , 'quad_with_wav' ] )
101108
102109
103110if __name__ == "__main__" :
0 commit comments