예제 #1
0
def apply_negative(column):
    result = np.ones_like(column).astype(np.float64) * np.nan
    negative_values = column.values > 2**15

    result[negative_values] = column[negative_values] - 2**16
    result[np.invert(negative_values)] = column[np.invert(negative_values)]

    if np.any(np.isnan(result)):
        raise Exception("Not all column values were converted")

    return result
예제 #2
0
def assert_array_agreement(unique_logfile_gantry_angles, mosaiq_gantry_angles,
                           allowed_deviation):
    difference_matrix = np.abs(unique_logfile_gantry_angles[:, None] -
                               mosaiq_gantry_angles[None, :])
    agreement_matrix = difference_matrix <= allowed_deviation
    row_agreement = np.any(agreement_matrix, axis=1)
    at_least_one_agreement = np.all(row_agreement)

    assert at_least_one_agreement, (
        "There is a logfile gantry angle that deviates by more than {} degrees"
        " from the Mosaiq control points. Unsure how to handle this.\n\n"
        "Logfile: {}\nMosaiq: {}\nDifference Matrix:\n{}\n"
        "Agreement Matrix:\n{}".format(
            allowed_deviation,
            unique_logfile_gantry_angles,
            mosaiq_gantry_angles,
            difference_matrix,
            agreement_matrix,
        ))
예제 #3
0
def convert_numbers_to_string(name, lookup, column):
    dtype = np.array([item for _, item in lookup.items()]).dtype
    result = np.empty_like(column).astype(dtype)
    result[:] = ""

    for i, item in lookup.items():
        result[column.values == int(i)] = item

    if np.any(result == ""):
        print(lookup)
        print(np.where(result == ""))
        print(column[result == ""].values)
        unconverted_entries = np.unique(column[result == ""])
        raise Exception(
            "The conversion lookup list for converting {} is incomplete. "
            "The following data numbers were not converted:\n"
            "{}\n"
            "Please update the trf2csv conversion script to include these "
            "in its definitions.".format(name, unconverted_entries))

    return result
예제 #4
0
def field_centre_and_rotation_refining(
    field,
    edge_lengths,
    penumbra,
    initial_centre,
    fixed_rotation=None,
    niter=10,
    pylinac_tol=0.2,
):

    if fixed_rotation is None:
        check_aspect_ratio(edge_lengths)

        predicted_rotation = optimise_rotation(field, initial_centre,
                                               edge_lengths, penumbra)
    else:
        predicted_rotation = fixed_rotation

    predicted_centre = optimise_centre(field, initial_centre, edge_lengths,
                                       penumbra, predicted_rotation)

    for _ in range(niter):
        if fixed_rotation is None:
            previous_rotation = predicted_rotation
            predicted_rotation = optimise_rotation(field, predicted_centre,
                                                   edge_lengths, penumbra)
            try:
                check_rotation_close(edge_lengths, previous_rotation,
                                     predicted_rotation)
                break
            except ValueError:
                pass

        previous_centre = predicted_centre
        predicted_centre = optimise_centre(field, predicted_centre,
                                           edge_lengths, penumbra,
                                           predicted_rotation)
        try:
            check_centre_close(previous_centre, predicted_centre)
            break
        except ValueError:
            pass

    if fixed_rotation is None:
        verification_rotation = optimise_rotation(field, predicted_centre,
                                                  edge_lengths, penumbra)

        check_rotation_close(edge_lengths, verification_rotation,
                             predicted_rotation)

    if not pylinac_tol is None:
        try:
            pylinac = run_wlutz(
                field,
                edge_lengths,
                penumbra,
                predicted_centre,
                predicted_rotation,
                find_bb=False,
            )
        except ValueError as e:
            raise ValueError(
                "After finding the field centre during comparison to Pylinac the pylinac "
                f"code raised the following error:\n    {e}")

        pylinac_2_2_6_out_of_tol = np.any(
            np.abs(
                np.array(pylinac["v2.2.6"]["field_centre"]) -
                predicted_centre) > pylinac_tol)
        pylinac_2_2_7_out_of_tol = np.any(
            np.abs(
                np.array(pylinac["v2.2.7"]["field_centre"]) -
                predicted_centre) > pylinac_tol)
        if pylinac_2_2_6_out_of_tol or pylinac_2_2_7_out_of_tol:
            raise PylinacComparisonDeviation(
                "The determined field centre deviates from pylinac more "
                "than the defined tolerance")

    centre = predicted_centre.tolist()
    return centre, predicted_rotation
예제 #5
0
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
예제 #6
0
def check_if_at_bounds(bb_centre, bb_bounds):
    x_at_bounds = np.any(np.array(bb_centre[0]) == np.array(bb_bounds[0]))
    y_at_bounds = np.any(np.array(bb_centre[1]) == np.array(bb_bounds[1]))

    any_at_bounds = x_at_bounds or y_at_bounds
    return any_at_bounds
예제 #7
0
파일: shell.py 프로젝트: lc52520/pymedphys
def gamma_loop(options: GammaInternalFixedOptions):
    still_searching_for_gamma = np.full_like(options.flat_dose_reference,
                                             True,
                                             dtype=bool)

    current_gamma = np.inf * np.ones((
        len(options.flat_dose_reference),
        len(options.dose_percent_threshold),
        len(options.distance_mm_threshold),
    ))

    distance_step_size = np.min(
        options.distance_mm_threshold) / options.interp_fraction

    to_be_checked = options.reference_points_to_calc & still_searching_for_gamma

    distance = 0.0

    force_search_distances = np.sort(options.distance_mm_threshold)
    while distance <= options.maximum_test_distance:
        if not options.quiet:
            sys.stdout.write(
                "\rCurrent distance: {0:.2f} mm | "
                "Number of reference points remaining: {1}".format(
                    distance, np.sum(to_be_checked)))

        min_relative_dose_difference = calculate_min_dose_difference(
            options, distance, to_be_checked, distance_step_size)

        current_gamma, still_searching_for_gamma_all = multi_thresholds_gamma_calc(
            options,
            current_gamma,
            min_relative_dose_difference,
            distance,
            to_be_checked,
        )

        still_searching_for_gamma = np.any(np.any(
            still_searching_for_gamma_all, axis=-1),
                                           axis=-1)

        to_be_checked = options.reference_points_to_calc & still_searching_for_gamma

        if np.sum(to_be_checked) == 0:
            break

        relevant_distances = options.distance_mm_threshold[np.any(
            np.any(
                options.reference_points_to_calc[:, None, None]
                & still_searching_for_gamma_all,
                axis=0,
            ),
            axis=0,
        )]

        distance_step_size = np.min(
            relevant_distances) / options.interp_fraction

        distance_step_size = np.max([
            distance / options.interp_fraction / options.max_gamma,
            distance_step_size
        ])

        distance += distance_step_size
        if len(force_search_distances) != 0:
            if distance >= force_search_distances[0]:
                distance = force_search_distances[0]
                force_search_distances = np.delete(force_search_distances, 0)

    return current_gamma