Как заставить Боке интерполировать палитру из 3 цветов

#interpolation #bokeh #heatmap #palette

Вопрос:

Я построил тепловую карту в Боке, которая отлично работает. Я хочу, чтобы он постоянно менял цвет с ярко-зеленого на ярко-красный. Текущий код является:

 colors = ["#66ff00", "#FFFFFF", "#FF0000"]
colors.reverse()
mapper = LinearColorMapper(palette=colors, low=-50, high=50)

p.rect(..., fill_color=transform('percentage', mapper))
 

Проблема в том, что на тепловой карте отображаются только 3 цвета. Я бы ожидал, что все значения от -50 до 50 будут линейно интерполировать значения от ярко-красного до белого до ярко-зеленого и отображаться на тепловой карте. Как я могу этого достичь?

Ответ №1:

Принятый в настоящее время ответ абсолютно правильный, я просто подумал, что любой, кто найдет это, может использовать рабочее решение для своей проблемы.

С помощью matplotlib вы можете создать линейную сегментированную цветовую карту:

 colors = ["darkorange", "gold", "lawngreen", "lightseagreen"]
cmap1 = matplotlib.colors.LinearSegmentedColormap.from_list("mycmap", colors)
 

Если ваши цвета не должны быть равномерно распределены по диапазону, вы также можете определить их положение:

 colors = ["darkorange", "gold", "lawngreen", "lightseagreen"]
nodes = [0.0, 0.4, 0.8, 1.0]
cmap2 = matplotlib.colors.LinearSegmentedColormap.from_list("mycmap", list(zip(nodes, colors)))
 

Отсюда вы можете обрабатывать эту цветовую карту так же, как и любую встроенную линейную сегментированную цветовую карту, например, медь. Например, вы можете экспортировать список из 192 цветов в диапазоне от 25% до 90% вашей цветовой карты следующим образом:

 palette = [matplotlib.colors.rgb2hex(c) for c in cmap1(np.linspace(0.25, 0.9, 192))]
 

А затем вы можете использовать эту палитру в любом решении для построения графиков, которое вы предпочитаете.

Редактировать: Поскольку мне также часто нужна точно такая же функциональность, я только что создал функцию для этого.

Сам код:

 def get_palette(cmap='Greys', n=192, start=0, end=1):
  import matplotlib, numpy as np

  linspace = np.linspace(start, end, n)

  if isinstance(cmap, list):
    cmap = matplotlib.colors.LinearSegmentedColormap.from_list("customcmap", cmap)
    palette = cmap(linspace)
  elif isinstance(cmap, str):
    cmap = matplotlib.pyplot.cm.get_cmap(cmap)
    palette = cmap(linspace)
  else:
    palette = cmap(linspace)

  hex_palette = [matplotlib.colors.rgb2hex(c) for c in palette]
  return hex_palette
 

Ответ №2:

Начиная с версии 2.3.1, палитры-это просто списки цветов, и существующие в настоящее время приложения для отображения цветов просто используют палитры, как указано, без их изменения. Если вам нужно больше цветов, вам нужно будет интерполировать палитру (список цветов) до нужного размера, прежде чем передавать ее Боке. «Линейный» в LinearColorMapper относится к тому, как значения линейно отображаются в ячейки, определенные палитрой.