def plot_gamma_hist(gamma, percent, dist): valid_gamma = gamma[~np.isnan(gamma)] plt.hist(valid_gamma, 50, density=True) pass_ratio = np.sum(valid_gamma <= 1) / len(valid_gamma) plt.title( "Local Gamma ({0}%/{1}mm) | Percent Pass: {2:.2f} % | Mean Gamma: {3:.2f} | Max Gamma: {4:.2f}" .format(percent, dist, pass_ratio * 100, np.mean(valid_gamma), np.max(valid_gamma)))
def plot_insert(insert_x, insert_y, width, length, circle_centre): circle, ellipse = visual_circle_and_ellipse(insert_x, insert_y, width, length, circle_centre) plt.figure() plt.plot(insert_x, insert_y) plt.axis("equal") plt.plot(circle["x"], circle["y"]) plt.title("Insert shape parameterisation") plt.xlabel("x (cm)") plt.ylabel("y (cm)") plt.grid(True) plt.plot(ellipse["x"], ellipse["y"])
def create_dvh(structure, dcm_struct, dcm_dose): structure_dose_values = find_dose_within_structure(structure, dcm_struct, dcm_dose) hist = np.histogram(structure_dose_values, 100) freq = hist[0] bin_edge = hist[1] bin_mid = (bin_edge[1::] + bin_edge[:-1:]) / 2 cumulative = np.cumsum(freq[::-1]) cumulative = cumulative[::-1] bin_mid = np.append([0], bin_mid) cumulative = np.append(cumulative[0], cumulative) percent_cumulative = cumulative / cumulative[0] * 100 plt.plot(bin_mid, percent_cumulative, label=structure) plt.title("DVH") plt.xlabel("Dose (Gy)") plt.ylabel("Relative Volume (%)")
def display_mu_density( grid, mu_density, grid_resolution=None, cmap=None, vmin=None, vmax=None ): """Prints a colour plot of the MU Density. Examples -------- See `pymedphys.mudensity.calculate`_. """ if grid_resolution is None: grid_resolution = grid["mlc"][1] - grid["mlc"][0] x, y = pcolormesh_grid(grid["mlc"], grid["jaw"], grid_resolution) plt.pcolormesh(x, y, mu_density, cmap=cmap, vmin=vmin, vmax=vmax) plt.colorbar() plt.title("MU density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.axis("equal") plt.gca().invert_yaxis()
def plot_model(width_data, length_data, factor_data): i, j, k = create_transformed_mesh(width_data, length_data, factor_data) model_width, model_length, model_factor = i, j, k # model_width_mesh, model_length_mesh = np.meshgrid( # model_width, model_length) vmin = np.nanmin( np.concatenate([model_factor.ravel(), factor_data.ravel()])) vmax = np.nanmax( np.concatenate([model_factor.ravel(), factor_data.ravel()])) # vrange = vmax - vmin plt.scatter( width_data, length_data, s=100, c=factor_data, cmap="viridis", vmin=vmin, vmax=vmax, zorder=2, ) plt.colorbar() cs = plt.contour(model_width, model_length, model_factor, 20, vmin=vmin, vmax=vmax) plt.clabel(cs, cs.levels[::2], inline=True) plt.title("Insert model") plt.xlabel("width (cm)") plt.ylabel("length (cm)")
def plot_and_save_results( reference_mudensity, evaluation_mudensity, gamma, gamma_options, png_record_directory, header_text="", footer_text="", ): reference_filepath = png_record_directory.joinpath("reference.png") evaluation_filepath = png_record_directory.joinpath("evaluation.png") diff_filepath = png_record_directory.joinpath("diff.png") gamma_filepath = png_record_directory.joinpath("gamma.png") diff = evaluation_mudensity - reference_mudensity imageio.imwrite(reference_filepath, reference_mudensity) imageio.imwrite(evaluation_filepath, evaluation_mudensity) imageio.imwrite(diff_filepath, diff) imageio.imwrite(gamma_filepath, gamma) largest_mu_density = np.max( [np.max(evaluation_mudensity), np.max(reference_mudensity)]) largest_diff = np.max(np.abs(diff)) widths = [1, 1] heights = [0.5, 1, 1, 1, 0.4] gs_kw = dict(width_ratios=widths, height_ratios=heights) fig, axs = plt.subplots(5, 2, figsize=(10, 16), gridspec_kw=gs_kw) gs = axs[0, 0].get_gridspec() for ax in axs[0, 0:]: ax.remove() for ax in axs[1, 0:]: ax.remove() for ax in axs[4, 0:]: ax.remove() ax_header = fig.add_subplot(gs[0, :]) ax_hist = fig.add_subplot(gs[1, :]) ax_footer = fig.add_subplot(gs[4, :]) ax_header.axis("off") ax_footer.axis("off") ax_header.text(0, 0, header_text, ha="left", wrap=True, fontsize=21) ax_footer.text(0, 1, footer_text, ha="left", va="top", wrap=True, fontsize=6) plt.sca(axs[2, 0]) pymedphys.mudensity.display(GRID, reference_mudensity, vmin=0, vmax=largest_mu_density) axs[2, 0].set_title("Reference MU Density") plt.sca(axs[2, 1]) pymedphys.mudensity.display(GRID, evaluation_mudensity, vmin=0, vmax=largest_mu_density) axs[2, 1].set_title("Evaluation MU Density") plt.sca(axs[3, 0]) pymedphys.mudensity.display(GRID, diff, cmap="seismic", vmin=-largest_diff, vmax=largest_diff) plt.title("Evaluation - Reference") plt.sca(axs[3, 1]) pymedphys.mudensity.display(GRID, gamma, cmap="coolwarm", vmin=0, vmax=2) plt.title("Local Gamma | " f"{gamma_options['dose_percent_threshold']}%/" f"{gamma_options['distance_mm_threshold']}mm") plt.sca(ax_hist) plot_gamma_hist( gamma, gamma_options["dose_percent_threshold"], gamma_options["distance_mm_threshold"], ) return fig
def plot_results( grid_xx, grid_yy, logfile_mu_density, mosaiq_mu_density, diff_colour_scale=0.1 ): min_val = np.min([logfile_mu_density, mosaiq_mu_density]) max_val = np.max([logfile_mu_density, mosaiq_mu_density]) plt.figure() plt.pcolormesh(grid_xx, grid_yy, logfile_mu_density, vmin=min_val, vmax=max_val) plt.colorbar() plt.title("Logfile MU density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.gca().invert_yaxis() plt.figure() plt.pcolormesh(grid_xx, grid_yy, mosaiq_mu_density, vmin=min_val, vmax=max_val) plt.colorbar() plt.title("Mosaiq MU density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.gca().invert_yaxis() scaled_diff = (logfile_mu_density - mosaiq_mu_density) / max_val plt.figure() plt.pcolormesh( grid_xx, grid_yy, scaled_diff, vmin=-diff_colour_scale / 2, vmax=diff_colour_scale / 2, ) plt.colorbar(label="Limited colour range = {}".format(diff_colour_scale / 2)) plt.title("(Logfile - Mosaiq MU density) / Maximum MU Density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.gca().invert_yaxis() plt.show() plt.figure() plt.pcolormesh( grid_xx, grid_yy, scaled_diff, vmin=-diff_colour_scale, vmax=diff_colour_scale ) plt.colorbar(label="Limited colour range = {}".format(diff_colour_scale)) plt.title("(Logfile - Mosaiq MU density) / Maximum MU Density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.gca().invert_yaxis() plt.show() absolute_range = np.max([-np.min(scaled_diff), np.max(scaled_diff)]) plt.figure() plt.pcolormesh( grid_xx, grid_yy, scaled_diff, vmin=-absolute_range, vmax=absolute_range ) plt.colorbar(label="No limited colour range") plt.title("(Logfile - Mosaiq MU density) / Maximum MU Density") plt.xlabel("MLC direction (mm)") plt.ylabel("Jaw direction (mm)") plt.gca().invert_yaxis() plt.show()
def optimise_bb_centre( field: imginterp.Field, bb_diameter, edge_lengths, penumbra, field_centre, field_rotation, pylinac_tol=0.2, debug=True, ): centralised_field = utilities.create_centralised_field( field, field_centre, field_rotation) to_minimise_edge_agreement = create_bb_to_minimise(centralised_field, bb_diameter) bb_bounds = define_bb_bounds(bb_diameter, edge_lengths, penumbra) bb_centre_in_centralised_field = bb_basinhopping( to_minimise_edge_agreement, bb_bounds) if check_if_at_bounds(bb_centre_in_centralised_field, bb_bounds): raise ValueError("BB found at bounds, likely incorrect") bb_centre = utilities.transform_point(bb_centre_in_centralised_field, field_centre, field_rotation) verification_repeat = bb_basinhopping(to_minimise_edge_agreement, bb_bounds) repeat_agreement = np.abs(verification_repeat - bb_centre_in_centralised_field) if np.any(repeat_agreement > BB_REPEAT_TOL): bb_repeated = utilities.transform_point(verification_repeat, field_centre, field_rotation) if debug: reporting.image_analysis_figure( field.x, field.y, field.img, bb_centre, field_centre, field_rotation, bb_diameter, edge_lengths, penumbra, ) plt.title("First iteration") reporting.image_analysis_figure( field.x, field.y, field.img, bb_repeated, field_centre, field_rotation, bb_diameter, edge_lengths, penumbra, ) plt.title("Second iteration") plt.show() raise ValueError("BB centre not able to be consistently determined\n" f" First iteration: {bb_centre}\n" f" Second iteration: {bb_repeated}") if not pylinac_tol is None: try: pylinac_result = pylinac.run_wlutz( field, edge_lengths, penumbra, field_centre, field_rotation, find_bb=True, pylinac_versions=("v2.2.6", ), ) except ValueError: raise ValueError( "While comparing result to PyLinac an error was raised") # warnings.simplefilter("always", UserWarning) # warnings.warn( # "This iteration has not been checked against pylinac. " # "When attempting to run pylinac instead an error was " # f"raised. Pylinac raised the following error:\n\n{e}\n" # ) # pylinac = {} try: pylinac_2_2_6_out_of_tol = np.any( np.abs( np.array(pylinac_result["v2.2.6"]["bb_centre"]) - bb_centre) > pylinac_tol) if pylinac_2_2_6_out_of_tol: raise pylinac.PylinacComparisonDeviation( "The determined bb centre deviates from pylinac more " "than the defined tolerance") except KeyError: pass return bb_centre