Example #1
0
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"])
Example #2
0
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
Example #3
0
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
Example #4
0
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()
Example #5
0
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))
Example #6
0
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