@@ -83,6 +83,7 @@ def plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, struct
8383 norm_flag = options ['norm_flag' ] if 'norm_flag' in options else False
8484 norm_volume = options ['norm_volume' ] if 'norm_volume' in options else 90
8585 norm_struct = options ['norm_struct' ] if 'norm_struct' in options else 'PTV'
86+ show_rx = options ['show_rx' ] if 'show_rx' in options else True
8687
8788 # plt.rcParams['font.size'] = font_size
8889 # plt.rc('font', family='serif')
@@ -106,15 +107,15 @@ def plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, struct
106107 norm_factor = Evaluation .get_dose (sol , dose_1d = dose_1d , struct = norm_struct , volume_per = norm_volume ) / pres
107108 dose_1d = dose_1d / norm_factor
108109 count = 0
109- for i in range (np .size (all_orgs )):
110- if all_orgs [i ] not in struct_names :
110+ for i in range (np .size (struct_names )):
111+ if struct_names [i ] not in all_orgs :
111112 continue
112- if my_plan .structures .get_fraction_of_vol_in_calc_box (all_orgs [i ]) == 0 : # check if the structure is within calc box
113- print ('Skipping Structure {} as it is not within calculation box.' .format (all_orgs [i ]))
113+ if my_plan .structures .get_fraction_of_vol_in_calc_box (struct_names [i ]) == 0 : # check if the structure is within calc box
114+ print ('Skipping Structure {} as it is not within calculation box.' .format (struct_names [i ]))
114115 continue
115116 # for dose_1d in dose_list:
116117 #
117- x , y = Evaluation .get_dvh (sol , struct = all_orgs [i ], dose_1d = dose_1d )
118+ x , y = Evaluation .get_dvh (sol , struct = struct_names [i ], dose_1d = dose_1d )
118119 if dose_scale == 'Absolute(Gy)' :
119120 max_dose = np .maximum (max_dose , x [- 1 ])
120121 ax .set_xlabel ('Dose (Gy)' , fontsize = fontsize )
@@ -129,10 +130,10 @@ def plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, struct
129130 ax .set_ylabel ('Volume (cc)' , fontsize = fontsize )
130131 elif volume_scale == 'Relative(%)' :
131132 max_vol = np .maximum (max_vol , y [0 ] * 100 )
132- ax .set_ylabel ('Volume Fraction ($\%$)' , fontsize = fontsize )
133- ax .plot (x , 100 * y , linestyle = style , linewidth = width , color = colors [count ])
133+ ax .set_ylabel ('Fractional Volume ($\%$)' , fontsize = fontsize )
134+ ax .plot (x , 100 * y , linestyle = style , linewidth = width , color = colors [count ], label = struct_names [ i ] )
134135 count = count + 1
135- legend .append (all_orgs [i ])
136+ # legend.append(struct_names [i])
136137
137138 if show_criteria is not None :
138139 for s in range (len (show_criteria )):
@@ -146,23 +147,30 @@ def plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, struct
146147 final_xmax = max (current_xlim [1 ], max_dose * 1.1 )
147148 ax .set_xlim (0 , final_xmax )
148149 ax .set_ylim (0 , max_vol )
149- ax .legend (legend , prop = {'size' : legend_font_size }, loc = legend_loc )
150+ # ax.legend(legend, prop={'size': legend_font_size}, loc=legend_loc)
151+ handles , labels = ax .get_legend_handles_labels ()
152+ # unique = [(h, l) for i, (h, l) in enumerate(zip(handles, labels)) if l not in labels[:i]]
153+ # Make all handles solid while ensuring unique legend entries
154+ unique = [(Line2D ([], [], color = h .get_color (), linestyle = '-' , lw = h .get_linewidth ()) if isinstance (h , Line2D ) else h , l )
155+ for i , (h , l ) in enumerate (zip (handles , labels )) if l not in labels [:i ]]
156+ ax .legend (* zip (* unique ), prop = {'size' : legend_font_size }, loc = legend_loc )
150157 ax .grid (visible = True , which = 'major' , color = '#666666' , linestyle = '-' )
151158
152159 # Show the minor grid lines with very faint and almost transparent grey lines
153160 # plt.minorticks_on()
154161 ax .minorticks_on ()
155- plt .grid (visible = True , which = 'minor' , color = '#999999' , linestyle = '--' , alpha = 0.2 )
156- y = np .arange (0 , 101 )
157- # if norm_flag:
158- # x = pres * np.ones_like(y)
159- # else:
160- if dose_scale == "Absolute(Gy)" :
161- x = pres * np .ones_like (y )
162- else :
163- x = 100 * np .ones_like (y )
162+ plt .grid (visible = True , which = 'minor' , color = '#999999' , linestyle = '--' , alpha = 0.5 )
163+ if show_rx :
164+ y = np .arange (0 , 101 )
165+ # if norm_flag:
166+ # x = pres * np.ones_like(y)
167+ # else:
168+ if dose_scale == "Absolute(Gy)" :
169+ x = pres * np .ones_like (y )
170+ else :
171+ x = 100 * np .ones_like (y )
164172
165- ax .plot (x , y , color = 'black' )
173+ ax .plot (x , y , color = 'black' )
166174 if title :
167175 ax .set_title (title )
168176 if show :
@@ -173,8 +181,8 @@ def plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, struct
173181
174182 @staticmethod
175183 def plot_robust_dvh (my_plan : Plan , sol : dict = None , dose_1d_list : list = None , struct_names : List [str ] = None ,
176- dose_scale : dose_type = "Absolute(Gy)" ,
177- volume_scale : volume_type = "Relative(%)" , plot_scenario = None , ** options ):
184+ dose_scale : dose_type = "Absolute(Gy)" ,
185+ volume_scale : volume_type = "Relative(%)" , plot_scenario = None , ** options ):
178186 """
179187 Create dvh plot for the selected structures
180188
@@ -278,7 +286,7 @@ def plot_robust_dvh(my_plan: Plan, sol: dict = None, dose_1d_list: list = None,
278286 ax .set_xlabel ('Dose (Gy)' , fontsize = fontsize )
279287 elif dose_scale == 'Relative(%)' :
280288 max_dose = np .maximum (max_dose , d_max_mat [- 1 ])
281- max_dose = max_dose / pres * 100
289+ max_dose = max_dose / pres * 100
282290 ax .set_xlabel ('Dose ($\%$)' , fontsize = fontsize )
283291
284292 if volume_scale == 'Absolute(cc)' :
@@ -287,7 +295,7 @@ def plot_robust_dvh(my_plan: Plan, sol: dict = None, dose_1d_list: list = None,
287295 ax .set_ylabel ('Volume (cc)' , fontsize = fontsize )
288296 elif volume_scale == 'Relative(%)' :
289297 max_vol = np .maximum (max_vol , y [0 ] * 100 )
290- ax .set_ylabel ('Volume Fraction ($\%$)' , fontsize = fontsize )
298+ ax .set_ylabel ('Fractional Volume ($\%$)' , fontsize = fontsize )
291299 # ax.plot(x, 100 * y, linestyle=style, linewidth=width, color=colors[count])
292300
293301 # ax.plot(d_min_mat, 100 * y, linestyle='dotted', linewidth=width*0.5, color=colors[count])
@@ -453,6 +461,7 @@ def plot_2d_slice(my_plan: Plan = None, sol: dict = None, dose_1d: np.ndarray =
453461
454462 Plot 2d view of ct, dose_1d, isodose and struct_name contours
455463
464+
456465 :param my_plan: object of class Plan
457466 :param sol: Optional solution to optimization
458467 :param dose_1d: Optional dose as 1d array
0 commit comments