Beispiel #1
0
def mlc_dd2dcm(mlc):
    mlc = np.array(mlc, copy=False)

    dicom_mlc_format = []
    for control_point in mlc:
        concatenated = np.hstack(
            [-control_point[-1::-1, 1], control_point[-1::-1, 0]])
        dicom_mlc_format.append(concatenated.astype(str).tolist())

    return dicom_mlc_format
Beispiel #2
0
def pcolormesh_grid(x, y, grid_resolution=None):
    if grid_resolution is None:
        diffs = np.hstack([np.diff(x), np.diff(y)])
        assert np.all(np.abs(diffs - diffs[0]) < 10 ** -12)

        grid_resolution = diffs[0]

    new_x = np.concatenate([x - grid_resolution / 2, [x[-1] + grid_resolution / 2]])
    new_y = np.concatenate([y - grid_resolution / 2, [y[-1] + grid_resolution / 2]])

    return new_x, new_y
Beispiel #3
0
def calculate_coordinates_shell_3d(distance, distance_step_size):
    """Create points along the surface of a sphere (a shell) where no gap
    between points is larger than the defined distance_step_size"""

    number_of_rows = np.ceil(np.pi * distance / distance_step_size).astype(int) + 1

    elevation = np.linspace(0, np.pi, number_of_rows)
    row_radii = distance * np.sin(elevation)
    row_circumference = 2 * np.pi * row_radii
    amount_in_row = np.ceil(row_circumference / distance_step_size).astype(int) + 1

    x_coords = []
    y_coords = []
    z_coords = []
    for i, phi in enumerate(elevation):
        azimuth = np.linspace(0, 2 * np.pi, amount_in_row[i] + 1)[:-1:]
        x_coords.append(distance * np.sin(phi) * np.cos(azimuth))
        y_coords.append(distance * np.sin(phi) * np.sin(azimuth))
        z_coords.append(distance * np.cos(phi) * np.ones_like(azimuth))

    return (np.hstack(x_coords), np.hstack(y_coords), np.hstack(z_coords))
Beispiel #4
0
def format_coords_for_dicom(all_merged):
    dicom_format_coords_by_z = {}

    for z, merged in all_merged.items():
        coords = get_coords_from_polygon_or_multipolygon(merged)
        new_contour_data = []
        for coord in coords:
            stacked_coords = np.hstack(
                list(zip(coord[0], coord[1], z * np.ones_like(coord[1]))))
            stacked_coords = np.round(stacked_coords, 1)
            stacked_coords = stacked_coords.tolist()

            new_contour_data.append(stacked_coords)

        dicom_format_coords_by_z[z] = new_contour_data

    return dicom_format_coords_by_z
def find_relevant_control_points(mu):
    """Returns that control points that had an MU difference either side.
    """
    mu_diff = np.diff(mu)
    no_change = mu_diff == 0
    try:
        start = no_change[0]
        end = no_change[-1]
    except IndexError:
        all_true = np.empty_like(mu).astype(bool)
        all_true.fill(True)
        return all_true

    no_change_before = no_change[0:-1]
    no_change_after = no_change[1::]

    no_change_before_and_after = no_change_before & no_change_after

    irrelevant_control_point = np.hstack(
        [start, no_change_before_and_after, end])
    relevant_control_points = np.invert(irrelevant_control_point)

    return relevant_control_points
Beispiel #6
0
def load_mephysto(filepath,
                  output_to_file=False,
                  output_directory=None,
                  sort=True):
    """Input the filepath of a mephysto .mcc file and return the data of the
    scans in four lists, distance, relative_dose, scan_curvetype, and
    scan_depth. Each respective element in these lists corresponds to an
    individual scan.
    """
    # Open the file and store the contents in file_contents
    with open(filepath) as file_pointer:
        file_contents = np.array(file_pointer.readlines())

    # Use the functions defined within mccread.py to pull the desired data
    distance, relative_dose = pull_mephysto_data(file_contents)
    scan_curvetype = pull_mephysto_item("SCAN_CURVETYPE", file_contents)
    scan_depth = pull_mephysto_number("SCAN_DEPTH", file_contents)

    # Convert python lists into numpy arrays for easier use
    distance = np.array(distance, dtype=object)
    relative_dose = np.array(relative_dose, dtype=object)
    scan_curvetype = np.array(scan_curvetype)
    scan_depth = np.array(scan_depth)

    # If the user requests to sort the data (which is default) the loaded
    # mephysto files are organised so that PDDs are first, then inplane
    # profiles, then crossplane profiles.
    if sort:
        # Find the references for where the scan type is the relevant type
        # and then use the "hstack" function to join the references together.
        sort_ref = np.hstack([
            np.where(scan_curvetype == "PDD")[0],  # reference of PDDs
            np.where(scan_curvetype == "INPLANE_PROFILE")[0],  # inplane ref
            np.where(scan_curvetype == "CROSSPLANE_PROFILE")[0],  # crossplane
        ])

        # Confirm that the length of sort_ref is the same as scan_curvetype.
        # This will be false if there exists an unexpected scan_curvetype.
        assert len(sort_ref) == len(scan_curvetype)

        # Apply the sorting reference to each of the relevant variables.
        distance = distance[sort_ref]
        relative_dose = relative_dose[sort_ref]
        scan_curvetype = scan_curvetype[sort_ref]
        scan_depth = scan_depth[sort_ref]

    # Output csv's if "output_to_file" is True
    if output_to_file:

        # If user didn't define an output_directory use a default one
        if output_directory is None:
            # Define output directory as a mephysto folder
            filepath_directory = os.path.dirname(filepath)
            filename = os.path.splitext(os.path.basename(filepath))[0]
            output_directory = os.path.join(filepath_directory, filename)

        # If the output directory does not exist create it
        if not os.path.exists(output_directory):
            os.makedirs(output_directory)

        # Call the file_output function within csvoutput.py
        file_output(output_directory, distance, relative_dose, scan_curvetype,
                    scan_depth)

    return distance, relative_dose, scan_curvetype, scan_depth