コード例 #1
0
def gamma_filter_brute_force(axes_reference,
                             dose_reference,
                             axes_evaluation,
                             dose_evaluation,
                             distance_mm_threshold,
                             dose_threshold,
                             lower_dose_cutoff=0,
                             **_):

    xx_ref, yy_ref, zz_ref = np.meshgrid(*axes_reference, indexing="ij")
    gamma_array = np.ones_like(dose_evaluation).astype(np.float) * np.nan

    mesh_index = np.meshgrid(
        *[np.arange(len(coord_eval)) for coord_eval in axes_evaluation])

    eval_index = np.reshape(np.array(mesh_index), (3, -1))
    run_index = np.arange(np.shape(eval_index)[1])
    np.random.shuffle(run_index)

    sys.stdout.write("    ")

    for counter, point_index in enumerate(run_index):
        i, j, k = eval_index[:, point_index]
        eval_x = axes_evaluation[0][i]
        eval_y = axes_evaluation[1][j]
        eval_z = axes_evaluation[2][k]

        if dose_evaluation[i, j, k] < lower_dose_cutoff:
            continue

        distance = np.sqrt((xx_ref - eval_x)**2 + (yy_ref - eval_y)**2 +
                           (zz_ref - eval_z)**2)

        dose_diff = dose_evaluation[i, j, k] - dose_reference

        gamma = np.min(
            np.sqrt((dose_diff / dose_threshold)**2 +
                    (distance / distance_mm_threshold)**2))

        gamma_array[i, j, k] = gamma

        if counter // 30 == counter / 30:
            percent_pass = str(
                np.round(calculate_pass_rate(gamma_array), decimals=1))
            sys.stdout.write(
                "\rPercent Pass: {0}% | Percent Complete: {1:.2f}%".format(
                    percent_pass, counter / np.shape(eval_index)[1] * 100))
            sys.stdout.flush()

    return calculate_pass_rate(gamma_array)
コード例 #2
0
def convert2_ratio_perim_area(width, length):
    """Convert width and length data into ratio of perimeter to area."""
    perimeter = (np.pi / 2 * (3 * (width + length) - np.sqrt(
        (3 * width + length) * (3 * length + width))))
    area = np.pi / 4 * width * length

    return perimeter / area
コード例 #3
0
def create_bb_attenuation_func(diameter, penumbra, max_attenuation):
    dx = diameter / 100
    radius = diameter / 2
    image_half_width = penumbra * 2 + radius

    x = np.arange(-image_half_width, image_half_width + dx, dx)
    xx, yy = np.meshgrid(x, x)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        z = np.sqrt(radius**2 - xx**2 - yy**2) / radius

    z[np.isnan(z)] = 0

    sig = profiles.scaled_penumbra_sig() * penumbra
    sig_pixel = sig / dx

    filtered = scipy.ndimage.gaussian_filter(z, sig_pixel)
    interp = scipy.interpolate.RegularGridInterpolator((x, x),
                                                       filtered,
                                                       bounds_error=False,
                                                       fill_value=None)

    def attenuation(x, y):
        return 1 - interp((x, y)) * max_attenuation

    return attenuation
コード例 #4
0
ファイル: shell.py プロジェクト: lc52520/pymedphys
def multi_thresholds_gamma_calc(
    options: GammaInternalFixedOptions,
    current_gamma,
    min_relative_dose_difference,
    distance,
    to_be_checked,
):

    gamma_at_distance = np.sqrt(
        (min_relative_dose_difference[:, None, None] /
         (options.dose_percent_threshold[None, :, None] / 100))**2 +
        (distance / options.distance_mm_threshold[None, None, :])**2)

    current_gamma[to_be_checked, :, :] = np.min(
        np.concatenate(
            [
                gamma_at_distance[None, :, :, :],
                current_gamma[None, to_be_checked, :, :],
            ],
            axis=0,
        ),
        axis=0,
    )

    still_searching_for_gamma = current_gamma > (
        distance / options.distance_mm_threshold[None, None, :])

    if options.skip_once_passed:
        still_searching_for_gamma = still_searching_for_gamma & (current_gamma
                                                                 >= 1)

    return current_gamma, still_searching_for_gamma
コード例 #5
0
ファイル: geometry.py プロジェクト: lc52520/pymedphys
    def distance_to(self, point):
        """Calculate the minimum distance from the line to a point.

        Equations are from here: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html #14

        Parameters
        ----------
        point : Point, iterable
            The point to calculate distance to.
        """
        point = Point(point).as_array()
        lp1 = self.point1.as_array()
        lp2 = self.point2.as_array()
        numerator = np.sqrt(
            np.sum(np.power(np.cross((lp2 - lp1), (lp1 - point)), 2)))
        denominator = np.sqrt(np.sum(np.power(lp2 - lp1, 2)))
        return numerator / denominator
コード例 #6
0
ファイル: geometry.py プロジェクト: lc52520/pymedphys
    def distance_to(self, thing: Union["Point", "Circle"]):
        """Calculate the distance to the given point.

        Parameters
        ----------
        thing : Circle, Point, 2 element iterable
            The other thing to calculate distance to.
        """
        if isinstance(thing, Circle):
            return abs(
                np.sqrt((self.x - thing.center.x)**2 +
                        (self.y - thing.center.y)**2) - thing.radius)
        p = Point(thing)
        return math.sqrt((self.x - p.x)**2 + (self.y - p.y)**2 +
                         (self.z - p.z)**2)
コード例 #7
0
ファイル: profiles.py プロジェクト: lc52520/pymedphys
def scaled_penumbra_sig(profile_shoulder_edge=0.8):
    sig = 1 / (2 * np.sqrt(2) *
               scipy.special.erfinv(profile_shoulder_edge * 2 - 1))

    return sig
コード例 #8
0
ファイル: profiles.py プロジェクト: lc52520/pymedphys
def gaussian_cdf(x, mu=0, sig=1):
    x = np.array(x, copy=False)
    return 0.5 * (1 + scipy.special.erf((x - mu) / (sig * np.sqrt(2))))
コード例 #9
0
def gamma_filter_numpy(axes_reference,
                       dose_reference,
                       axes_evaluation,
                       dose_evaluation,
                       distance_mm_threshold,
                       dose_threshold,
                       lower_dose_cutoff=0,
                       **_):

    coord_diffs = [
        coord_ref[:, None] - coord_eval[None, :]
        for coord_ref, coord_eval in zip(axes_reference, axes_evaluation)
    ]

    all_in_vicinity = [
        np.where(np.abs(diff) < distance_mm_threshold) for diff in coord_diffs
    ]

    ref_coord_points = create_point_combination(
        [in_vicinity[0] for in_vicinity in all_in_vicinity])

    eval_coord_points = create_point_combination(
        [in_vicinity[1] for in_vicinity in all_in_vicinity])

    distances = np.sqrt(
        np.sum(
            [
                coord_diff[ref_points, eval_points]**2
                for ref_points, eval_points, coord_diff in zip(
                    ref_coord_points, eval_coord_points, coord_diffs)
            ],
            axis=0,
        ))

    within_distance_threshold = distances < distance_mm_threshold

    distances = distances[within_distance_threshold]
    ref_coord_points = ref_coord_points[:, within_distance_threshold]
    eval_coord_points = eval_coord_points[:, within_distance_threshold]

    dose_diff = (
        dose_evaluation[eval_coord_points[0, :], eval_coord_points[1, :],
                        eval_coord_points[2, :]] -
        dose_reference[ref_coord_points[0, :], ref_coord_points[1, :],
                       ref_coord_points[2, :]])

    gamma = np.sqrt((dose_diff / dose_threshold)**2 +
                    (distances / distance_mm_threshold)**2)

    gamma_pass = gamma < 1

    eval_pass = eval_coord_points[:, gamma_pass]

    ravel_index = convert_to_ravel_index(eval_pass)
    gamma_pass_array = np.zeros_like(dose_evaluation).astype(np.bool)

    gamma_pass_array = np.ravel(gamma_pass_array)
    dose_above_cut_off = np.ravel(dose_evaluation) > lower_dose_cutoff

    gamma_pass_array[ravel_index] = True
    gamma_pass_percentage = np.mean(gamma_pass_array[dose_above_cut_off]) * 100

    return gamma_pass_percentage
コード例 #10
0
ファイル: reporting.py プロジェクト: lc52520/pymedphys
def image_with_overlays(
    fig,
    ax,
    x,
    y,
    img,
    field_transform,
    bb_centre,
    field_centre,
    bb_diameter,
    edge_lengths,
    x_field_interp,
    y_field_interp,
    x_bb_interp,
    y_bb_interp,
    pixel_value_label,
    units="(mm)",
):
    rect_crosshair_dx = [
        -edge_lengths[0] / 2,
        edge_lengths[0],
        -edge_lengths[0],
        edge_lengths[0],
    ]
    rect_crosshair_dy = [
        -edge_lengths[1] / 2, edge_lengths[1], 0, -edge_lengths[1]
    ]

    rect_dx = [-edge_lengths[0] / 2, 0, edge_lengths[0], 0, -edge_lengths[0]]
    rect_dy = [-edge_lengths[1] / 2, edge_lengths[1], 0, -edge_lengths[1], 0]

    c = ax.contourf(x, y, img, 100)
    fig.colorbar(c, ax=ax, label=pixel_value_label)

    ax.plot(*draw_by_diff(rect_dx, rect_dy, field_transform), "k", lw=3)
    ax.plot(*draw_by_diff(rect_crosshair_dx, rect_crosshair_dy,
                          field_transform),
            "k",
            lw=1)

    ax.plot(x_field_interp[0], x_field_interp[1], "k", lw=0.5, alpha=0.3)
    ax.plot(y_field_interp[0], y_field_interp[1], "k", lw=0.5, alpha=0.3)

    if bb_centre is not None:
        bb_radius = bb_diameter / 2
        bb_crosshair = np.array([-bb_radius, bb_radius])

        t = np.linspace(0, 2 * np.pi)
        circle_x_origin = bb_diameter / 2 * np.sin(t)
        circle_y_origin = bb_diameter / 2 * np.cos(t)

        circle_x = circle_x_origin + bb_centre[0]
        circle_y = circle_y_origin + bb_centre[1]

        ax.plot([bb_centre[0]] * 2, bb_crosshair + bb_centre[1], "k", lw=1)
        ax.plot(bb_crosshair + bb_centre[0], [bb_centre[1]] * 2, "k", lw=1)

        ax.plot(circle_x, circle_y, "k", lw=3)

        ax.plot(x_bb_interp[0], x_bb_interp[1], "k", lw=0.5, alpha=0.3)
        ax.plot(y_bb_interp[0], y_bb_interp[1], "k", lw=0.5, alpha=0.3)

        ax.plot(
            [field_centre[0], bb_centre[0]],
            [field_centre[1], bb_centre[1]],
            c="C3",
            lw=3,
        )

    ax.axis("equal")
    long_edge = np.sqrt(np.sum((np.array(edge_lengths))**2))
    long_edge_fraction = long_edge * 0.6

    ax.set_xlim([
        field_centre[0] - long_edge_fraction,
        field_centre[0] + long_edge_fraction
    ])
    ax.set_ylim([
        field_centre[1] - long_edge_fraction,
        field_centre[1] + long_edge_fraction
    ])

    ax.set_xlabel(f"iView panel absolute x-pos {units}")
    ax.set_ylabel(f"iView panel absolute y-pos {units}")