Подтвердить что ты не робот

Почему у моего colorbar есть строки?

Изменить. Поскольку это, кажется, популярный пост, вот решение, которое, кажется, работает хорошо для меня. Спасибо @gazzar и @mfra.

cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")

Кто-нибудь знает, почему у моего colorbar есть какие-то строки? Вернее, почему переход цвета не является гладким? Я использую базовую карту, очевидно, но это не имеет значения, так как все matplotlib вызывает под капотом AFAICT. Я создаю карту, делая что-то вроде

grays = plt.cm.get_cmap("Grays")
sc = mymap.scatter(xpoints, ypoints, s=sizes, c=color_values, cmap=grays, alpha=.75,
                   marker="o", zorder=10, vmin=0, vmax=1)
cbar = mymap.colorbar(sc, drawedges=True, location="bottom")

Я пробовал без альфы и без нее, и результат был таким же. Может быть, это потому, что мой массив color_values ​​не достаточно хорош? Могу ли я установить базовые значения, которые отображаются в цветовой панели где-нибудь? Я не понимаю, как, и я не вижу этой проблемы в другом месте. Т.е., я могу реплицировать пример matplotlib show_colorbars без этой проблемы.

Bad Colorbar Example

4b9b3361

Ответ 1

Если вы создаете векторную графику, попробовали ли вы это (взято из http://matplotlib.org/api/pyplot_api.html?highlight=colorbar#matplotlib.pyplot.colorbar):

"Известно, что некоторые средства просмотра векторной графики (svg и pdf) визуализируют белые промежутки между сегментами цветной панели. Это связано с ошибками в зрителях, а не с matplotlib. В качестве обходного пути цветная панель может отображаться с перекрывающимися сегментами:

cbar = colorbar()
cbar.solids.set_edgecolor("face")
draw()

Однако это имеет негативные последствия в других обстоятельствах. В частности, с полупрозрачными изображениями (альфа < 1) и расширением цветной панели и по умолчанию не включен (номер # 1188).

Ответ 2

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

cbar.solids.set_rasterized(True) 

Это обходное решение, по-видимому, не выполняется для изображений с прозрачностью, но для большинства нормальных случаев оно дает желаемый результат.

Ответ 3

Похоже, ваш сюжет использует некоторые прозрачные (альфа-значения). У меня была такая же проблема (полупрозрачный сюжет, но хотелось, чтобы цветная полоска была сплошной), и это question и answer исправил это для меня! Для справки:

cbar.set_alpha(1)
cbar.draw_all()

Ответ 4

Я попробовал оба параметра, указанные в других комментариях, а именно

cbar.solids.set_rasterized(True)
cbar.solids.set_edgecolor("face")

и, к сожалению, я не работал у меня.

Итак, я попробовал совершенно другой подход, который является огромным взломом, но, по крайней мере, выполняет свою работу. Когда вы проходите от alpha до imshow, он устанавливает альфа-значение, которое будет использоваться для смешивания с другими изображениями. Из-за причин повышенной мощности (как упоминал @mfra) это создает белые линии, которые мы так презираем. Очевидно, что тогда ключ не должен передавать значение альфа-значения в imshow. Однако нам все равно нужно как-то создать цветную панель.

Таким образом, в качестве обходного пути мы можем сделать альфа-смешивание, прежде чем давать цветовые карты imshow. В качестве примера можно использовать winter colormap:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

xx, yy = np.meshgrid(np.linspace(-1, 1, 100), np.linspace(-1, 1, 100))
zz = xx**2 + yy**2

my_cmap_rgb = plt.get_cmap('winter')(np.arange(256))
alpha = 0.5

for i in range(3): # Do not include the last column!
    my_cmap_rgb[:,i] = (1 - alpha) + alpha*my_cmap_rgb[:,i]
my_cmap = mpl.colors.ListedColormap(my_cmap_rgb, name='my_cmap')

Здесь я создаю новый colormap, my_cmap_rgb, на основе winter, а затем редактирую не-альфа-каналы (0, 1 и 2), чтобы выполнить альфа-смешение. Затем я могу просто использовать эту новую цветочную карту для построения моей фигуры.

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
ax.set_title("No lines and no transparency")

Нет строк и прозрачности Теперь сравните его с изображением, которое вы получите без этого трюка:

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap='winter', alpha=0.5)
cbar = plt.colorbar(cim)
ax.set_title("Lines and transparency")

Линии и прозрачность

Ясно, что проблема решена, если вам не нужна прозрачность. С другой стороны, если вы требуете прозрачности, есть еще одно обходное решение. Вы должны сначала построить изображение без прозрачности, чтобы получить цветную панель, а затем построить один с прозрачностью, но цветная панель не будет использоваться.

f, ax = plt.subplots()
cim = ax.imshow(zz, cmap=my_cmap)
cbar = plt.colorbar(cim)
plt.cla()  # Clears axis
ax.plot(50,50, 'ko')
ax.imshow(zz, cmap='winter', alpha=0.5)
ax.set_title("No lines and transparency")

В результате получается изображение, цветная строка которого не имеет линий и при этом сохраняет прозрачность. В то время как это остается массивным взломом, по крайней мере, нам больше не придется мириться с этими строками!

Нет строк и прозрачности

Ответ 5

Try:

cbar = mymap.colorbar(sc, drawedges=False, location="bottom")

Теперь он хорошо документирован в Интернете (что я мог найти), но

*drawedges*   [ False | True ] If true, draw lines at color
              boundaries.

(вытащил из matplotlib/lib/matplotlib/colorbar.py) Я думаю, установив drawedges в True, вы говорите ему, чтобы рисовать эти строки.

Ответ 6

Следующее может быть другим решением, даже если оно не изящно.

In [1]: children = cbar.ax.get_children()
In [2]: children
Out[2]:
[<matplotlib.collections.QuadMesh at 0x21783c41b70>,
 <matplotlib.collections.LineCollection at 0x21783bfdc18>,
 <matplotlib.patches.Polygon at 0x21783ba0588>,
 <matplotlib.patches.Polygon at 0x21783beef98>,
 <matplotlib.spines.Spine at 0x21783b77c88>,
 <matplotlib.spines.Spine at 0x21783b77470>,
 <matplotlib.spines.Spine at 0x21783b70c88>,
 <matplotlib.spines.Spine at 0x21783b70860>,
 <matplotlib.axis.XAxis at 0x21783b6ac50>,
 <matplotlib.axis.YAxis at 0x21783ba60f0>,
 <matplotlib.text.Text at 0x21783bc2198>,
 <matplotlib.text.Text at 0x21783bc2320>,
 <matplotlib.text.Text at 0x21783bc22b0>,
 <matplotlib.patches.Rectangle at 0x21783bc2358>]
In [3]: obj = children[1]  # Get the LineCollection object
In [4]: obj.set_linewidth(0)