Skip to content

Commit c65ac10

Browse files
committed
add generate_quantive_colors
1 parent b875d8c commit c65ac10

File tree

3 files changed

+470
-1
lines changed

3 files changed

+470
-1
lines changed

PyComplexHeatmap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .dotHeatmap import *
99
from .colors import *
1010
from .utils import set_default_style
11-
11+
import fire
1212
# __all__=['*']
1313
from ._version import version as __version__
1414
# __version__ = "1.6.5"

PyComplexHeatmap/colors.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
from .utils import _calculate_luminance
88
import pandas as pd
99
default_cmaps = matplotlib.pyplot.colormaps()
10+
import colorsys
11+
import numpy as np
12+
from matplotlib import colors as mcolors
13+
named_colors=mcolors.CSS4_COLORS
14+
named_colors.update(mcolors.BASE_COLORS) #kes is color string, values are hex
15+
# named_colors.update(mcolors.TABLEAU_COLORS)
16+
named_colors.update(mcolors.CSS4_COLORS)
17+
for k in named_colors:
18+
if isinstance(named_colors[k],tuple):
19+
named_colors[k]=mcolors.to_hex(named_colors[k])
1020

1121
def register_cmap(c):
1222
try:
@@ -266,6 +276,52 @@ def register_palettable():
266276
c = LinearSegmentedColormap.from_list(name, colors)
267277
register_cmap(c)
268278

279+
def identify_color_format(color):
280+
if color in named_colors:
281+
return 'named_color'
282+
elif isinstance(color, str) and color.startswith('#'):
283+
if len(color) == 7 or len(color) == 4:
284+
return 'HEX'
285+
elif isinstance(color, tuple) and len(color) == 3:
286+
if all(isinstance(val, int) and 0 <= val <= 255 for val in color):
287+
return 'RGB (integer)'
288+
elif all(isinstance(val, float) and 0 <= val <= 1 for val in color):
289+
return 'RGB (float)'
290+
elif isinstance(color, tuple) and len(color) == 3:
291+
h, l, s = color
292+
if (isinstance(h, float) and 0 <= h <= 1) or (isinstance(h, int) and 0 <= h <= 360):
293+
if isinstance(l, float) and 0 <= l <= 1 and isinstance(s, float) and 0 <= s <= 1:
294+
return 'HLS'
295+
return 'Unknown'
296+
297+
def interpolate_colors(color1, color2, num_colors, fmt='RGB'):
298+
if fmt == 'HLS':
299+
color1 = colorsys.hls_to_rgb(*color1)
300+
color2 = colorsys.hls_to_rgb(*color2)
301+
elif fmt != 'RGB':
302+
color1 = mcolors.to_rgb(color1)
303+
color2 = mcolors.to_rgb(color2)
304+
color1 = np.array(color1)
305+
color2 = np.array(color2)
306+
colors = [tuple(color1 + (color2 - color1) * i / (num_colors - 1)) for i in range(num_colors)]
307+
return colors
308+
309+
310+
def generate_quantive_colors(color, n=5, white=(0.9, 0.9, 0.9), black=(0.3, 0.3, 0.3), ret_fmt='HEX'):
311+
fmt = identify_color_format(color)
312+
if not fmt.startswith('RGB'):
313+
color = mcolors.to_rgb(color)
314+
light_colors = interpolate_colors(white, color, n // 2 + 2)[1:-1] # from white to color
315+
dark_colors = interpolate_colors(color, black, n // 2 + 2)[1:-1] # from color to black;white=(1,1,1),black=(0,0,0)
316+
if len(light_colors) + len(dark_colors) == n:
317+
results = light_colors + dark_colors
318+
else:
319+
results = light_colors + [color] + dark_colors
320+
if ret_fmt == 'RGB':
321+
return results
322+
elif ret_fmt == 'HEX':
323+
return [mcolors.to_hex(c) for c in results]
324+
269325
try:
270326
define_cmap()
271327
except:

0 commit comments

Comments
 (0)