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 calc_calibration_points(prescans, postscans, alignments=None, figures=False, pixel_trim=0): """Returns calibration points based on dictionaries of prescans and postscans. The key of the dictionaries of images is to represent the dose calibration point. If the key cannot be converted into a float that image will be ignored. """ keys = prescans.keys() assert keys == postscans.keys() calibration_points = {} if alignments is None: alignments = {key: None for key in keys} for key in keys: try: dose_value = float(key) except ValueError: warnings.warn( "{} does not appear to be a calibration image key. This will " "be skipped.") continue net_od, alignment = calc_net_od(prescans[key], postscans[key], alignment=alignments[key]) if pixel_trim != 0: trim_ref = (slice(pixel_trim, -pixel_trim), slice(pixel_trim, -pixel_trim)) net_od = net_od[trim_ref] if figures: plt.figure() plt.imshow(net_od) plt.show() calibration_points[dose_value] = np.median(net_od) alignments[key] = alignment return calibration_points, alignments
def plot_cube(cube_definition): points_matplotlib_order = cube_vertices(cube_definition) points = points_matplotlib_order.copy() points[:, 0], points[:, 1] = points[:, 1], points[:, 0].copy() edges = [ [points[0], points[3], points[5], points[1]], [points[1], points[5], points[7], points[4]], [points[4], points[2], points[6], points[7]], [points[2], points[6], points[3], points[0]], [points[0], points[2], points[4], points[1]], [points[3], points[6], points[7], points[5]], ] fig = plt.figure() ax = fig.add_subplot(111, projection="3d") faces = mpl_toolkits.mplot3d.art3d.Poly3DCollection( edges, linewidths=1, edgecolors="k" ) faces.set_facecolor((0, 0, 1, 0.1)) ax.add_collection3d(faces) bounding_box = get_bounding_box(points_matplotlib_order) ax.set_xlim(bounding_box[1]) ax.set_ylim(bounding_box[0]) ax.set_zlim(bounding_box[2]) # ax.set_aspect('equal') ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("z") ax.set_aspect("equal") return ax
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 main(): st.write(""" # Electron Insert Factors """) patient_id = st.text_input("Patient ID") if patient_id == "": st.stop() rccc_string_search_pattern = r"\\monacoda\FocalData\RCCC\1~Clinical\*~{}\plan\*\*tel.1".format( patient_id) rccc_filepath_list = glob(rccc_string_search_pattern) nbccc_string_search_pattern = r"\\tunnel-nbcc-monaco\FOCALDATA\NBCCC\1~Clinical\*~{}\plan\*\*tel.1".format( patient_id) nbccc_filepath_list = glob(nbccc_string_search_pattern) sash_string_search_pattern = r"\\tunnel-sash-monaco\Users\Public\Documents\CMS\FocalData\SASH\1~Clinical\*~{}\plan\*\*tel.1".format( patient_id) sash_filepath_list = glob(sash_string_search_pattern) filepath_list = np.concatenate( [rccc_filepath_list, nbccc_filepath_list, sash_filepath_list]) electronmodel_regex = r"RiverinaAgility - (\d+)MeV" applicator_regex = r"(\d+)X\d+" insert_data = dict() # type: ignore for telfilepath in filepath_list: insert_data[telfilepath] = dict() with open(telfilepath, "r") as file: telfilecontents = np.array(file.read().splitlines()) insert_data[telfilepath]["reference_index"] = [] for i, item in enumerate(telfilecontents): if re.search(electronmodel_regex, item): insert_data[telfilepath]["reference_index"] += [i] insert_data[telfilepath]["applicators"] = [ re.search(applicator_regex, telfilecontents[i + 12]).group(1) # type: ignore for i in insert_data[telfilepath]["reference_index"] ] insert_data[telfilepath]["energies"] = [ re.search(electronmodel_regex, telfilecontents[i]).group(1) # type: ignore for i in insert_data[telfilepath]["reference_index"] ] for telfilepath in filepath_list: with open(telfilepath, "r") as file: telfilecontents = np.array(file.read().splitlines()) insert_data[telfilepath]["x"] = [] insert_data[telfilepath]["y"] = [] for i, index in enumerate(insert_data[telfilepath]["reference_index"]): insert_initial_range = telfilecontents[ index + 51::] # coords start 51 lines after electron model name insert_stop = np.where(insert_initial_range == "0")[0][ 0] # coords stop right before a line containing 0 insert_coords_string = insert_initial_range[:insert_stop] insert_coords = np.fromstring(",".join(insert_coords_string), sep=",") insert_data[telfilepath]["x"].append(insert_coords[0::2] / 10) insert_data[telfilepath]["y"].append(insert_coords[1::2] / 10) for telfilepath in filepath_list: insert_data[telfilepath]["width"] = [] insert_data[telfilepath]["length"] = [] insert_data[telfilepath]["circle_centre"] = [] insert_data[telfilepath]["P/A"] = [] for i in range(len(insert_data[telfilepath]["reference_index"])): width, length, circle_centre = electronfactors.parameterise_insert( insert_data[telfilepath]["x"][i], insert_data[telfilepath]["y"][i]) insert_data[telfilepath]["width"].append(width) insert_data[telfilepath]["length"].append(length) insert_data[telfilepath]["circle_centre"].append(circle_centre) insert_data[telfilepath]["P/A"].append( electronfactors.convert2_ratio_perim_area(width, length)) data_filename = r"S:\Physics\RCCC Specific Files\Dosimetry\Elekta_EFacs\electron_factor_measured_data.csv" data = pd.read_csv(data_filename) width_data = data["Width (cm @ 100SSD)"] length_data = data["Length (cm @ 100SSD)"] factor_data = data["RCCC Inverse factor (dose open / dose cutout)"] p_on_a_data = electronfactors.convert2_ratio_perim_area( width_data, length_data) for telfilepath in filepath_list: insert_data[telfilepath]["model_factor"] = [] for i in range(len(insert_data[telfilepath]["reference_index"])): applicator = float(insert_data[telfilepath]["applicators"][i]) energy = float(insert_data[telfilepath]["energies"][i]) ssd = 100 reference = ((data["Energy (MeV)"] == energy) & (data["Applicator (cm)"] == applicator) & (data["SSD (cm)"] == ssd)) number_of_measurements = np.sum(reference) if number_of_measurements < 8: insert_data[telfilepath]["model_factor"].append(np.nan) else: insert_data[telfilepath]["model_factor"].append( electronfactors.spline_model_with_deformability( insert_data[telfilepath]["width"], insert_data[telfilepath]["P/A"], width_data[reference], p_on_a_data[reference], factor_data[reference], )[0]) for telfilepath in filepath_list: st.write("---") st.write("Filepath: `{}`".format(telfilepath)) for i in range(len(insert_data[telfilepath]["reference_index"])): applicator = float(insert_data[telfilepath]["applicators"][i]) energy = float(insert_data[telfilepath]["energies"][i]) ssd = 100 st.write("Applicator: `{} cm` | Energy: `{} MeV`".format( applicator, energy)) width = insert_data[telfilepath]["width"][i] length = insert_data[telfilepath]["length"][i] plt.figure() plot_insert( insert_data[telfilepath]["x"][i], insert_data[telfilepath]["y"][i], insert_data[telfilepath]["width"][i], insert_data[telfilepath]["length"][i], insert_data[telfilepath]["circle_centre"][i], ) reference = ((data["Energy (MeV)"] == energy) & (data["Applicator (cm)"] == applicator) & (data["SSD (cm)"] == ssd)) number_of_measurements = np.sum(reference) plt.figure() if number_of_measurements < 8: plt.scatter( width_data[reference], length_data[reference], s=100, c=factor_data[reference], cmap="viridis", zorder=2, ) plt.colorbar() else: plot_model( width_data[reference], length_data[reference], factor_data[reference], ) reference_data_table = pd.concat( [ width_data[reference], length_data[reference], factor_data[reference] ], axis=1, ) reference_data_table.sort_values( ["RCCC Inverse factor (dose open / dose cutout)"], ascending=False, inplace=True, ) st.write(reference_data_table) st.pyplot() factor = insert_data[telfilepath]["model_factor"][i] st.write( "Width: `{0:0.2f} cm` | Length: `{1:0.2f} cm` | Factor: `{2:0.3f}`" .format(width, length, factor))
def merge_view_filtrot(volume, dx, dy): volume_resort = np.copy( volume ) # this will hold the resorted volume 0 to 3 clockwise junctions_comb = [] peaks_figs_comb = [] # we need to create 4 matches # 0,1,2,3 will be tagged top left, top right, bottom right, bottom left for i in range(0, int(np.shape(volume)[2])): diag_stack = [ 0, 0, 0, 0, ] # we will sum along one direction whichever is biggest will tag the file for j in range(0, int(min([np.shape(volume)[0], np.shape(volume)[1]]) / 2)): # print('j=',j,int(np.shape(volume)[0] / 2)+j, int(np.shape(volume)[1] / 2)+j) diag_stack[0] = ( diag_stack[0] + volume[ int(np.shape(volume)[0] / 2) - j, int(np.shape(volume)[1] / 2) - j, i, ] ) diag_stack[1] = ( diag_stack[1] + volume[ int(np.shape(volume)[0] / 2) - j, int(np.shape(volume)[1] / 2) + j, i, ] ) diag_stack[2] = ( diag_stack[2] + volume[ int(np.shape(volume)[0] / 2) + j, int(np.shape(volume)[1] / 2) + j, i, ] ) diag_stack[3] = ( diag_stack[3] + volume[ int(np.shape(volume)[0] / 2) + j, int(np.shape(volume)[1] / 2) - j, i, ] ) volume_resort[:, :, np.argmax(diag_stack)] = volume[:, :, i] # creating merged volumes merge_vol = np.zeros((volume_resort.shape[0], volume_resort.shape[1])) # creating vector for processing (1 horizontal & 1 vertical) amplitude_horz = np.zeros( (volume_resort.shape[1], volume_resort.shape[2]) ) # 1 if it is vertical 0 if the bars are horizontal amplitude_vert = np.zeros((volume_resort.shape[0], volume_resort.shape[2])) # y = np.linspace(0, 0 + (volume_resort.shape[0] * dy), volume_resort.shape[0], # endpoint=False) # definition of the distance axis # x = np.linspace(0, 0 + (volume_resort.shape[1] * dy), volume_resort.shape[1], # endpoint=False) # definition of the distance axis ampl_resamp_y1 = np.zeros( ((volume_resort.shape[0]) * 10, int(volume_resort.shape[2] / 2)) ) ampl_resamp_y2 = np.zeros( ((volume_resort.shape[0]) * 10, int(volume_resort.shape[2] / 2)) ) ampl_resamp_x1 = np.zeros( ((volume_resort.shape[1]) * 10, int(volume_resort.shape[2] / 2)) ) ampl_resamp_x2 = np.zeros( ((volume_resort.shape[1]) * 10, int(volume_resort.shape[2] / 2)) ) amplitude_horz[:, 0] = volume_resort[ int(volume_resort.shape[0] / 3.25), :, 0 ] # for profile 1 amplitude_horz[:, 1] = volume_resort[ int(volume_resort.shape[0] / 3.25), :, 1 ] # for profile 1 amplitude_horz[:, 3] = volume_resort[ int(volume_resort.shape[0]) - int(volume_resort.shape[0] / 3.25), :, 2 ] # the numbers here are reversed because we are going to slide the second graph (the overlay) to minimize the error #for profile 2 amplitude_horz[:, 2] = volume_resort[ int(volume_resort.shape[0]) - int(volume_resort.shape[0] / 3.25), :, 3 ] amplitude_vert[:, 0] = volume_resort[ :, int(volume_resort.shape[1]) - int(volume_resort.shape[1] / 2.8), 1 ] # the numbers here are reversed because we are going to slide the second graph (the overlay) to minimize the error #for profile 3 amplitude_vert[:, 1] = volume_resort[ :, int(volume_resort.shape[1]) - int(volume_resort.shape[1] / 2.8), 2 ] amplitude_vert[:, 3] = volume_resort[ :, int(volume_resort.shape[1] / 2.8), 3 ] # for profile 4 amplitude_vert[:, 2] = volume_resort[:, int(volume_resort.shape[1] / 2.8), 0] plt.figure() for item in tqdm(range(0, int(volume.shape[2] / 2))): merge_vol = merge_vol + volume[:, :, item] data_samp = amplitude_vert[:, item] ampl_resamp_y1[:, item] = signal.resample( data_samp, int(np.shape(amplitude_vert)[0]) * 10 ) data_samp = amplitude_horz[:, item] ampl_resamp_x1[:, item] = signal.resample( data_samp, int(np.shape(amplitude_horz)[0]) * 10 ) for item in tqdm(range(int(volume.shape[2] / 2), volume.shape[2])): merge_vol = merge_vol + volume[:, :, item] data_samp = amplitude_vert[:, item] ampl_resamp_y2[:, item - int(volume.shape[2] / 2)] = signal.resample( data_samp, int(np.shape(amplitude_vert)[0]) * 10 ) data_samp = amplitude_horz[:, item] ampl_resamp_x2[:, item - int(volume.shape[2] / 2)] = signal.resample( data_samp, int(np.shape(amplitude_horz)[0]) * 10 ) fig, ax = plt.subplots(ncols=1, nrows=1, squeeze=True, figsize=(6, 8)) extent = (0, 0 + (volume.shape[1] * dx), 0, 0 + (volume.shape[0] * dy)) ax.imshow(merge_vol, extent=extent, aspect="auto") ax.set_aspect("equal", "box") ax.set_xlabel("x distance [mm]") ax.set_ylabel("y distance [mm]") fig.suptitle("Merged volume", fontsize=16) ax.hlines(dy * int(volume_resort.shape[0] / 3.25), 0, dx * volume_resort.shape[1]) ax.text( dx * int(volume_resort.shape[1] / 2.25), dy * int(volume_resort.shape[0] / 3), "Profile 2", ) ax.hlines( dy * int(volume_resort.shape[0]) - dy * int(volume_resort.shape[0] / 3.25), 0, dx * volume_resort.shape[1], ) ax.text( dx * int(volume_resort.shape[1] / 2.25), dy * int(volume_resort.shape[0]) - dy * int(volume_resort.shape[0] / 3.5), "Profile 1", ) ax.vlines(dx * int(volume_resort.shape[1] / 2.8), 0, dy * volume_resort.shape[0]) ax.text( dx * int(volume_resort.shape[1] / 3.1), dy * int(volume_resort.shape[0] / 1.8), "Profile 4", rotation=90, ) ax.vlines( dx * int(volume_resort.shape[1]) - dx * int(volume_resort.shape[1] / 2.8), 0, dy * volume_resort.shape[0], ) ax.text( dx * int(volume_resort.shape[1]) - dx * int(volume_resort.shape[1] / 2.9), dy * int(volume_resort.shape[0] / 1.8), "Profile 3", rotation=90, ) # plt.show() peaks, peak_type, peak_figs = pffr.peak_find_fieldrot( ampl_resamp_x1, dx, "Profile 1" ) junction_figs = minFR.minimize_junction_fieldrot( ampl_resamp_x1, peaks, peak_type, dx / 10, "Profile 1" ) peaks_figs_comb.append(peak_figs) junctions_comb.append(junction_figs) peaks, peak_type, peak_figs = pffr.peak_find_fieldrot( ampl_resamp_x2, dx, "Profile 2" ) junction_figs = minFR.minimize_junction_fieldrot( ampl_resamp_x2, peaks, peak_type, dx / 10, "Profile 2" ) peaks_figs_comb.append(peak_figs) junctions_comb.append(junction_figs) peaks, peak_type, peak_figs = pffr.peak_find_fieldrot( ampl_resamp_y1, dy, "Profile 3" ) junction_figs = minFR.minimize_junction_fieldrot( ampl_resamp_y1, peaks, peak_type, dy / 10, "Profile 3" ) peaks_figs_comb.append(peak_figs) junctions_comb.append(junction_figs) peaks, peak_type, peak_figs = pffr.peak_find_fieldrot( ampl_resamp_y2, dy, "Profile 4" ) junction_figs = minFR.minimize_junction_fieldrot( ampl_resamp_y2, peaks, peak_type, dy / 10, "Profile 4" ) peaks_figs_comb.append(peak_figs) junctions_comb.append(junction_figs) return fig, peaks_figs_comb, junctions_comb