def get_kernel(shifts, shift_vals):
        """
        Get all kernels describing the path of the edges in a discrete raster
        :param shifts: possible circle points
        :returns kernel: all possible kernels
        shape: (number of circle points x upper x upper)
        :returns posneg: a list indicating whether it is a path to the left =1
        or to the right =0
        """
        upper = np.amax(np.absolute(shifts)) + 1
        posneg = []
        kernel = np.zeros((len(shifts), upper, upper))

        max_val = np.max(shift_vals)

        for i, shift in enumerate(shifts):
            if shift[1] < 0:
                posneg.append(1)
                line = bresenham_line(0, upper - 1, shift[0],
                                      upper - 1 + shift[1])
            else:
                posneg.append(0)
                line = bresenham_line(0, 0, shift[0], shift[1])
            # add points of line to the kernel
            normed_val = shift_vals[i] / (len(line) * max_val)
            for (j, k) in line:
                kernel[i, j, k] = normed_val
        return kernel, posneg
Exemple #2
0
    def set_shift(
        self,
        start,
        dest,
        pylon_dist_min=3,
        pylon_dist_max=5,
        max_angle=np.pi / 2,
        max_angle_lg=np.pi / 2,
        **kwargs
    ):
        """
        Initialize shift variable by getting the donut values
        :param pylon_dist_min, pylon_dist_max: min and max distance of pylons
        :param vec: vector of diretion of edges
        :param max_angle: Maximum angle of edges to vec
        """
        self.start_inds = np.asarray(start)
        self.dest_inds = np.asarray(dest)
        self.angle_norm_factor = max_angle_lg
        vec = self.dest_inds - self.start_inds
        shifts = get_half_donut(
            pylon_dist_min, pylon_dist_max, vec, angle_max=max_angle
        )
        shift_angles = [angle_360(s, vec) for s in shifts]
        # sort the shifts
        self.shifts = np.asarray(shifts)[np.argsort(shift_angles)]
        self.shift_tuples = self.shifts

        # construct bresenham lines
        shift_lines = List()
        for shift in self.shifts:
            line = bresenham_line(0, 0, shift[0], shift[1])
            shift_lines.append(np.array(line[1:-1]))
        self.shift_lines = shift_lines
def cells_crossed_plot(
    folders, disp_inst, out_path=None, buffer=4, line_buffer=2
):
    """
    Plotting function to visualize how often each cell is crossed
    Arguments:
        folders: List of directory paths that contain the paths to analyze
        disp_inst: 2D array, instance to display and plot the paths on
        out_path: saving fp for plot
    """
    # e.g. path_dir ["sensitivity_tuples", "weight_sensitivity_0905",
    # "optimal_paths", "weight_sensitivity_0905", "layer_sensitivity"]
    path_list = []
    for path in folders:
        for fn in os.listdir(
            os.path.join("../../outputs/de_presentation", path)
        ):
            if fn[-3:] == "csv":
                path_table = pd.read_csv(
                    os.path.join("../../outputs/de_presentation", path, fn)
                )
                path_list.append((np.asarray(path_table[["X_raw", "Y_raw"]])))

    x_len, y_len = disp_inst.shape
    mark_array = np.zeros((y_len, x_len))
    for path in path_list:  # path_tuple_list
        path = np.asarray(path).astype(int)
        for p in range(len(path)):
            (i, j) = path[p]
            mark_array[i:i + buffer + 1, j:j + buffer +
                       1] = mark_array[i:i + buffer + 1, j:j + buffer + 1] + 1
            if p < len(path) - 1:
                (k, l) = path[p + 1]
                line_points = bresenham_line(i, j, k, l)
                for (x, y) in line_points[1:-1]:
                    mark_array[x:x + line_buffer, y:y +
                               line_buffer] = mark_array[x:x +
                                                         line_buffer, y:y +
                                                         line_buffer] + 1

    grey_disp_inst = np.tile(np.expand_dims(disp_inst, 2), 3)
    x_nonzero, y_nonzero = np.where(mark_array > 0)
    max_val = np.max(mark_array)
    for (x, y) in zip(x_nonzero, y_nonzero):
        normed = mark_array[x, y] / (max_val - 200)
        grey_disp_inst[y, x] = [
            np.clip(1 - normed, 0, 1),
            np.clip(normed + 0.3, 0, 1), 0.2
        ]

    plt.figure(figsize=(20, 20))
    plt.imshow(grey_disp_inst)
    if out_path is not None:
        plt.savefig(out_path + ".png")
    else:
        plt.show()
Exemple #4
0
 def compute_edge_costs(path, instance):
     e_costs = []
     for p in range(len(path) - 1):
         point_list = bresenham_line(path[p][0], path[p][1], path[p + 1][0],
                                     path[p + 1][1])
         e_costs.append(
             np.mean([instance[i, j] for (i, j) in point_list[1:-1]]))
     # to make it the same size as other costs
     e_costs.append(0)
     return e_costs
 def test_edge_costs(self) -> None:
     graph = graphs.ImplicitLG(np.array([self.example_inst]),
                               self.working_expl_corr,
                               n_iters=10,
                               verbose=0)
     self.cfg.angle_weight = 0
     self.cfg.edge_weight = 0.5
     path, path_costs, cost_sum = graph.single_sp(**vars(self.cfg))
     self.cfg.angle_weight = 0.25
     self.cfg.edge_weight = 0
     dest_ind = graph.pos2node[tuple(self.dest_inds)]
     dest_costs = np.min(graph.dists[dest_ind])
     dest_costs_gt = len(path)  # everywhere 1
     a = []
     path = np.array(path)
     for p in range(len(path) - 1):
         line = bresenham_line(path[p, 0], path[p, 1], path[p + 1, 0],
                               path[p + 1, 1])[1:-1]
         line_costs = [self.example_inst[i, j] for (i, j) in line]
         line_costs = [l for l in line_costs if l < np.inf]
         a.append(np.mean(line_costs) * 0.5)
     dest_costs_gt += np.sum(a)
     self.assertEqual(dest_costs, dest_costs_gt)
     self.assertEqual(dest_costs, cost_sum)
class TestImplicitLG(unittest.TestCase):

    expl_shape = (50, 50)

    # create configuration
    cfg = SimpleNamespace()
    cfg.pylon_dist_min = 3
    cfg.pylon_dist_max = 5
    start_inds = np.array([6, 6])
    dest_inds = np.array([41, 43])
    cfg.start_inds = start_inds
    cfg.dest_inds = dest_inds
    cfg.angle_weight = 0.25
    cfg.edge_weight = 0
    cfg.max_angle = np.pi / 2
    cfg.max_angle_lg = np.pi / 4
    cfg.layer_classes = ["dummy_class"]
    cfg.class_weights = [1]

    # construct simple line instance
    example_inst = np.ones(expl_shape)
    # construct corresponding corridor
    working_expl_corr = np.zeros(expl_shape)
    line = bresenham_line(start_inds[0], start_inds[1], dest_inds[0],
                          dest_inds[1])
    for (i, j) in line:
        working_expl_corr[i - 1:i + 1, j - 1:j + 1] = 1

    # construct instance that required 90 degree angle
    high_angle_corr = np.zeros(expl_shape)
    high_angle_corr[start_inds[0], start_inds[1]:dest_inds[1] - 3] = 1
    high_angle_corr[start_inds[0], dest_inds[1]] = 1
    high_angle_corr[start_inds[0] + 3:dest_inds[0] + 1, dest_inds[1]] = 1

    def test_correct_shortest_path(self) -> None:
        """ Test the implicit line graph construction """
        graph = graphs.ImplicitLG(np.array([self.example_inst]),
                                  self.working_expl_corr,
                                  n_iters=10,
                                  verbose=0)
        path, path_costs, cost_sum = graph.single_sp(**vars(self.cfg))
        self.assertListEqual(graph.cost_weights.tolist(), [0.2, 0.8])
        self.assertTupleEqual(graph.instance.shape, self.expl_shape)
        self.assertEqual(np.sum(graph.cost_weights), 1)
        self.assertNotEqual(len(graph.shifts), 0)
        # all initialized to infinity
        # self.assertTrue(not np.any([graph.dists[graph.dists < np.inf]]))
        # start point was set to normalized value
        start_ind = graph.pos2node[tuple(self.start_inds)]
        self.assertEqual(0.8, graph.dists[start_ind, 0])
        # all start dists have same value
        self.assertEqual(len(np.unique(graph.dists[start_ind])), 1)
        # not all values still inf
        self.assertLess(np.min(graph.dists[start_ind]), np.inf)
        # get actual best path
        # path, path_costs, cost_sum = graph.get_shortest_path(
        #     self.start_inds, self.dest_inds
        # )
        self.assertNotEqual(len(path), 0)
        self.assertEqual(len(path), len(path_costs))
        self.assertGreaterEqual(cost_sum, 5)
        weighted_costs = np.sum(path_costs, axis=0) * graph.cost_weights
        self.assertEqual(np.sum(weighted_costs), cost_sum)
        for (i, j) in path:
            self.assertEqual(self.example_inst[i, j], 1)

    def test_edge_costs(self) -> None:
        graph = graphs.ImplicitLG(np.array([self.example_inst]),
                                  self.working_expl_corr,
                                  n_iters=10,
                                  verbose=0)
        self.cfg.angle_weight = 0
        self.cfg.edge_weight = 0.5
        path, path_costs, cost_sum = graph.single_sp(**vars(self.cfg))
        self.cfg.angle_weight = 0.25
        self.cfg.edge_weight = 0
        dest_ind = graph.pos2node[tuple(self.dest_inds)]
        dest_costs = np.min(graph.dists[dest_ind])
        dest_costs_gt = len(path)  # everywhere 1
        a = []
        path = np.array(path)
        for p in range(len(path) - 1):
            line = bresenham_line(path[p, 0], path[p, 1], path[p + 1, 0],
                                  path[p + 1, 1])[1:-1]
            line_costs = [self.example_inst[i, j] for (i, j) in line]
            line_costs = [l for l in line_costs if l < np.inf]
            a.append(np.mean(line_costs) * 0.5)
        dest_costs_gt += np.sum(a)
        self.assertEqual(dest_costs, dest_costs_gt)
        self.assertEqual(dest_costs, cost_sum)

    def test_angle_sp(self) -> None:
        graph = graphs.ImplicitLG(np.array([self.example_inst]),
                                  self.high_angle_corr,
                                  n_iters=10,
                                  verbose=0)
        path, path_costs, cost_sum = graph.single_sp(**vars(self.cfg))
        # assert that destination can NOT be reached
        dest_ind = graph.pos2node[tuple(self.dest_inds)]
        self.assertFalse(np.min(graph.dists[dest_ind]) < np.inf)

        # NEXT TRY: more angles allowed
        self.cfg.max_angle_lg = np.pi
        graph = graphs.ImplicitLG(np.array([self.example_inst]),
                                  self.high_angle_corr,
                                  n_iters=10,
                                  verbose=0)
        path, path_costs, cost_sum = graph.single_sp(**vars(self.cfg))
        # assert that dest CAN be reached
        dest_ind = graph.pos2node[tuple(self.dest_inds)]
        self.assertTrue(np.min(graph.dists[dest_ind]) < np.inf)

        # same with linegraph:
        lg_graph = graphs.LineGraph(np.array([self.example_inst]),
                                    self.high_angle_corr,
                                    verbose=0)
        path_lg, path_costs_lg, cost_sum_lg = lg_graph.single_sp(
            **vars(self.cfg))
        self.cfg.max_angle_lg = np.pi / 4
        # assert that path is non-empty
        self.assertTrue(len(path_lg) > 0)
        self.assertEqual(len(path_lg), len(path_costs_lg))
        self.assertGreaterEqual(cost_sum_lg, 5)
        weighted_costs = np.sum(path_costs_lg, axis=0) * lg_graph.cost_weights
        self.assertEqual(np.sum(weighted_costs), cost_sum_lg)
        # assert that all points are equal to 1
        for (i, j) in path_lg:
            self.assertEqual(self.example_inst[i, j], 1)

        lg_graph = graphs.LineGraph(np.array([self.example_inst]),
                                    self.high_angle_corr,
                                    verbose=0)
        path_lg, path_costs_lg, cost_sum_lg = lg_graph.single_sp(
            **vars(self.cfg))
        self.assertTrue(len(path_lg) == 0)