flow-free / utils.py
darwinharianto's picture
first commit
b37334e
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