"""_summary_
author: Herman Huanan Zhao
email: hermanzhaozzzz@gmail.com
homepage: https://github.com/hermanzhaozzzz
_description_
example 1:
bioat list
<in shell>:
$ bioat list
<in python consolo>:
>>> from bioat.cli import Cli
>>> bioat = Cli()
>>> bioat.list()
>>> print(bioat.list())
example 2:
_example_
"""
import math
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
from bioat.logger import LoggerManager
lm = LoggerManager(mod_name="bioat.lib.libcolor")
[docs]
def plot_colortable(colors, *, ncols=4, sort_colors=True, labels=None):
cell_width = 212
cell_height = 22
swatch_width = 48
margin = 12
names = list(colors)
if not labels:
labels = names
n = len(names)
nrows = math.ceil(n / ncols)
width = cell_width * 4 + 2 * margin
height = cell_height * nrows + 2 * margin
dpi = 72
fig, ax = plt.subplots(figsize=(width / dpi, height / dpi), dpi=dpi)
fig.subplots_adjust(margin / width, margin / height,
(width - margin) / width, (height - margin) / height)
ax.set_xlim(0, cell_width * 4)
ax.set_ylim(cell_height * (nrows - 0.5), -cell_height / 2.)
ax.yaxis.set_visible(False)
ax.xaxis.set_visible(False)
ax.set_axis_off()
for i, name in enumerate(names):
row = i % nrows
col = i // nrows
y = row * cell_height
swatch_start_x = cell_width * col
text_pos_x = cell_width * col + swatch_width + 7
ax.text(text_pos_x, y, labels[i], fontsize=14,
horizontalalignment='left',
verticalalignment='center')
ax.add_patch(
Rectangle(xy=(swatch_start_x, y - 9), width=swatch_width,
height=18, facecolor=name, edgecolor='0.7')
)
return fig
[docs]
def convert_hex_to_rgb(hex_color: str) -> tuple:
"""Convert HEX color to RGB color.
:param hex_color: str, like '#FFFFAA'
:return: tuple, like (255, 255, 170)
"""
value = hex_color.lstrip('#')
value_len = len(value)
return tuple(int(value[index: index + 2], 16) for index in range(0, value_len, 2))
[docs]
def convert_rgb_to_hex(rgb_color: tuple) -> str:
"""Convert RGB color to HEX color.
:param rgb_color: tuple, like (255, 255, 170)
:return: str, like '#FFFFAA'
"""
rgb_color = ('#%02x%02x%02x' % rgb_color).upper()
return rgb_color
[docs]
def map_color(value_vec, breaks, color_list):
"""
INPUT:
<value_vec>
np.array or a list of values
<breaks>
A sorted value list, which can split all num into len(color_list) intervals.
e.g. [0.01, 0.1, 0.5, 1] make all real num into 5 intervals, (-Inf,0.01], (0.01,0.1], (0.1, 0.5], (0.5, 1], (1, +Inf]
<color_list>
A hex-format color list, which have to match with breaks
RETURN
<value_color_vec>
A list map the value_vec with breaks
"""
value_idx_list = []
for value in value_vec:
match_state = False
for index, break_value in enumerate(breaks):
if value <= break_value:
value_idx_list.append(index)
match_state = True
break
if not match_state:
value_idx_list.append(index + 1)
return tuple(color_list[col_idx] for col_idx in value_idx_list)
[docs]
def make_color_list(low_color_RGB, high_color_RGB, length_out=20, return_fmt="HEX", log_level='DEBUG'):
"""
INPUT
<low_color_RGB> <high_color_RGB>
Format like (210, 179, 150), tuple, list, or np.array
<back_format>
Hex OR RGB
RETURN
<color_list>
"""
lm.set_names(func_name="make_color_list")
lm.set_level(log_level)
return_fmt = return_fmt.upper()
supported_fmt = ('HEX', 'RGB')
if return_fmt not in supported_fmt:
lm.logger.critical(
f"not supported color format: {return_fmt}\n"
f"supported_fmt = {supported_fmt}"
)
low_color = np.array(low_color_RGB)
high_color = np.array(high_color_RGB)
color_list = []
for index in range(0, length_out + 1):
rgb_color = [abs(i) for i in low_color + (high_color - low_color) // length_out * index]
if return_fmt == "HEX":
color_list.append(convert_rgb_to_hex(tuple(rgb_color)))
else:
color_list.append(tuple(rgb_color))
return color_list
[docs]
def map_colors_between_two(base_color, target_color, values):
"""
在两个指定颜色之间根据数值映射生成颜色。
Args:
base_color (str): 起始颜色,格式为 '#RRGGBB'。
target_color (str): 结束颜色,格式为 '#RRGGBB'。
values (list or array): 数值数组,范围可为任意值。
Return:
list: 对应颜色数组(#RRGGBB 格式)。
"""
# 创建自定义线性颜色映射
cmap = mcolors.LinearSegmentedColormap.from_list(
"custom_cmap", [base_color, target_color]
)
# 归一化数据到 [0, 1]
norm = mcolors.Normalize(vmin=min(values), vmax=max(values))
# 映射数值到颜色
colors = [mcolors.rgb2hex(cmap(norm(value))) for value in values]
return colors
if __name__ == '__main':
# %%% test func plot_colortable
colors = ['#64C1E8',
'#80CED7',
'#63C7B2',
'#8E6C88',
'#CA61C3',
'#FF958C',
'#883677']
plot_colortable(colors, ncols=1, labels=[1, 2, 3, 4, 5, 6, 7])
# plt.show()