import numpy as np import time import logging def print_time(before): logging.info(time.time() - before) return time.time() def linewidth_from_data_units(linewidth, axis, reference="y"): """ Convert a linewidth in data units to linewidth in points. Parameters ---------- linewidth: float Linewidth in data units of the respective reference-axis axis: matplotlib axis The axis which is used to extract the relevant transformation data (data limits and size must not change afterwards) reference: string The axis that is taken as a reference for the data width. Possible values: 'x' and 'y'. Defaults to 'y'. Returns ------- linewidth: float Linewidth in points """ fig = axis.get_figure() if reference == "x": length = fig.bbox_inches.width * axis.get_position().width value_range = np.diff(axis.get_xlim())[0] elif reference == "y": length = fig.bbox_inches.height * axis.get_position().height value_range = np.diff(axis.get_ylim())[0] # Convert length to points length *= 72 # Scale linewidth to value range return linewidth * (length / value_range) def add_walls_and_source_to_ax(ax, colors, S, scatter_size): s_mat = np.array(S) M, N = s_mat.shape[0], s_mat.shape[1] scatter_dict = {"color_item_-1_x_y": []} for iter in range(np.sum(np.unique(s_mat) > 0)): scatter_dict[f"color_item_{iter+1}_x_y"] = [] for i in range(M): for j in range(N): if S[i][j] != 0: scatter_dict[f"color_item_{S[i][j]}_x_y"].append([j, i]) for key in scatter_dict: color_item = int(key.split("_")[2]) mat = np.array(scatter_dict[key]).T if len(mat) == 0: continue j = mat[0].tolist() i = mat[1].tolist() ax.scatter( j, i, s=scatter_size * 2, color=colors[color_item] if color_item != 0 else "black", marker="x" if color_item < 0 else None, ) def plot_area(S): import matplotlib import matplotlib.pyplot as plt from matplotlib import colors ax = plt.gca() color = [matplotlib.colors.to_hex(c) for c in plt.cm.tab20.colors] s_mat = np.array(S) M, N = s_mat.shape[0], s_mat.shape[1] # create discrete colormap # print(color[:s_mat.max()] + color[-1]) cmap = colors.ListedColormap([color[-1]] + color[: s_mat.max() + 1]) # cmap = colors.ListedColormap(['red', 'blue', 'green', 'yellow', 'black']) bounds = [i for i in np.arange(-1, s_mat.max() + 2, 1)] norm = colors.BoundaryNorm(bounds, cmap.N) ax.imshow(s_mat + 0.5, cmap=cmap, norm=norm, alpha=0.5) # half is for the threshold # draw gridlines ax.set_facecolor("black") ax.set_ylim(M - 0.5, -0.5) ax.set_xlim(-0.5, N - 0.5) return ax.figure def plot_walls(S): import matplotlib.pyplot as plt plt.clf() plt.cla() ax = plt.gca() colors = plt.cm.tab20.colors s_mat = np.array(S) M, N = s_mat.shape[0], s_mat.shape[1] linewidth = linewidth_from_data_units(0.45, ax) ax.set_ylim(M - 0.5, -0.5) ax.set_xlim(-0.5, N - 0.5) ax.set_aspect("equal") ax.set_facecolor("black") ax.set_yticks([i + 0.5 for i in range(M - 1)], minor=True) ax.set_xticks([j + 0.5 for j in range(N - 1)], minor=True) ax.grid(b=True, which="minor", color="white") ax.set_xticks([]) ax.set_yticks([]) ax.tick_params(axis="both", which="both", length=0) add_walls_and_source_to_ax(ax, colors, S, linewidth) logging.info("finish plot_walls for right side") return ax.figure def put_num_on_matrix(m, walls, in_num): matrix = np.copy(m) for coords in walls: x_min, x_max, y_min, y_max = coords[0], coords[2], coords[1], coords[3] for x in range( x_min, x_max + 1 if (x_min < x_max) else x_max - 1, 1 if (x_min < x_max) else -1, ): x = int(x) for y in range( y_min, y_max + 1 if (y_min < y_max) else y_max - 1, 1 if (y_min < y_max) else -1, ): y = int(y) if y < len(matrix) and x < len(matrix[0]) and matrix is not None: matrix[y][x] = in_num return matrix def put_rect_source_on_matrix(matrix, coords): number_of_source = 0 x_min, x_max, y_min, y_max = coords[0], coords[2], coords[1], coords[3] for x in range( x_min, x_max + 1 if (x_min < x_max) else x_max - 1, 1 if (x_min < x_max) else -1 ): x = int(x) for y in range( y_min, y_max + 1 if (y_min < y_max) else y_max - 1, 1 if (y_min < y_max) else -1, ): y = int(y) matrix[y][x] = int(number_of_source / 2) + 1 number_of_source += 1 assert number_of_source % 2 == 0 and "Number of source outlet must be mutiply of 2!" return matrix def put_point_source_on_matrix(matrix, coords): number_of_source = len(matrix) assert number_of_source % 2 == 0 and "Number of source outlet must be mutiply of 2!" for x, y, col in coords: matrix[int(y)][int(x)] = col return matrix def create_matrix_and_area_matrix(color_dict, canvas_size, pipe_size, source, arr): matrix = np.zeros( (np.array(canvas_size) / np.array(pipe_size)).astype("int").tolist() ).astype("int") area_matrix = None color_set = list(set([item.split("_")[-1] for item in color_dict.keys()])) for index in color_set: for start_point, end_point in zip( color_dict[f"start_{index}"], color_dict[f"end_{index}"] ): # graph.draw_rectangle(start_point, end_point, fill_color=colors[int(index)], line_color=colors[int(index)]) start = np.array(start_point) end = np.array(end_point) start[1] = canvas_size[1] - start[1] end[1] = canvas_size[1] - end[1] start[0], start[1], end[0], end[1] = ( start[0] / pipe_size[0], start[1] / pipe_size[1], end[0] / pipe_size[0], end[1] / pipe_size[1], ) arr = ( np.append(arr, [np.append(start, end)], axis=0) if arr is not None else np.append(start, end).reshape(-1, 4) ) # this means wall if int(index) == -1: matrix = put_num_on_matrix(matrix, arr, in_num=-1) area_matrix = ( put_num_on_matrix(area_matrix, arr, in_num=int(index)) if area_matrix is not None else put_num_on_matrix(matrix, arr, in_num=int(index)) ) arr = None if source: if len(source[0]) == 2: start_x = source[0][0] / pipe_size[0] end_x = source[1][0] / pipe_size[0] start_y = (canvas_size[1] - source[0][1]) / pipe_size[1] end_y = (canvas_size[1] - source[1][1]) / pipe_size[1] source_sized = np.array([start_x, start_y, end_x, end_y]).astype("int") matrix = put_rect_source_on_matrix(matrix, source_sized) elif len(source[0]) == 3: source_sized = [] for i in range(len(source)): x = source[i][0] / pipe_size[0] y = (canvas_size[1] - source[i][1]) / pipe_size[1] col = source[i][2] source_sized.append([x, y, col]) matrix = put_point_source_on_matrix(matrix, source_sized) return matrix, area_matrix if __name__ == "__main__": matrix = [ [-1, 0, 1, 1], [-1, 0, 2, 2], [-1, 0, 0, 0], ] areamatrix = [ [-1, 0, 1, 1], [-1, 0, 1, 1], [-1, 0, 2, 2], ] plot_walls(matrix) plot_area(areamatrix) pass