web-dev-qa-db-ja.com

カラーバーに線が入っているのはなぜですか?

編集:これは人気のある投稿のようですので、これが私にとってうまく機能しているように見える解決策です。 @gazzarと@mfraに感謝します。

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

私のカラーバーに線のように見えるものがある理由を誰かが知っていますか?というか、なぜ色の変化がスムーズでないのですか?私は明らかにベースマップを使用していますが、それはすべてAFAICTの内部でのmatplotlib呼び出しであるため、それは問題ではありません。私は次のようなことをして地図を作成します

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配列が十分に細かくないためですか?カラーバーにマップされる基になる値をどこかに設定できますか?方法がわかりませんし、他の場所でもこの問題は見られません。つまり、この問題なしにmatplotlibshow_colorbarsの例を複製できます。

Bad Colorbar Example

42
jseabold

ベクターグラフィックを作成する場合は、これを試しましたか( 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)を参照してください。」

28
mfra

プロットがいくつかの透明な(アルファ)値を使用しているようです。私はこれと同じ問題を抱えていました(半透明のプロットですが、カラーバーを塗りつぶしたかったです)、そしてこれは 質問回答 私のためにそれを修正しました!参考のために:

cbar.set_alpha(1)
cbar.draw_all()
9
Wesley Baugh

私は通常、Eric Firingのアドバイスを使用してこの問題を回避するためにカラーバーの内容をラスタライズすることを好みます ここ 次の行を追加します。

cbar.solids.set_rasterized(True) 

この回避策は、透明度のある画像では失敗すると思われますが、ほとんどの場合、望ましい結果が得られます。

8
gazzar

私は他のコメントで与えられた両方の設定を試しました、すなわち

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

残念ながら、どちらも私にはうまくいきませんでした。

それで、私は巨大なハックである完全に異なるアプローチを試みました、しかし少なくとも仕事を成し遂げます。 alphaimshowに渡すと、他の画像とのブレンドに使用されるアルファ値が設定されます。 (@mfraが述べたように)より高いパワーの理由により、これは私たちがとても軽蔑する白い線を作成します。明らかに重要なのは、notにアルファ値をimshowに渡すことです。ただし、どういうわけかカラーバーを作成する必要があります。

したがって、回避策として、imshowにカラーマップを与える前に、自分でアルファブレンディングを行うことができます。例として、winterカラーマップを使用してみましょう。

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')

ここでは、winterに基づいて新しいカラーマップmy_cmap_rgbを作成し、非アルファチャネル(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")

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")

Lines and transparency

透明性が必要ない場合は、明らかに問題が解決されます。一方、透明性が必要な場合は、もう1つの回避策があります。カラーバーを取得するには、最初に透明度のない画像をプロットしてから、透明度のある画像をプロットする必要がありますが、そのカラーバーは使用されません。

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")

これにより、カラーバーに線がなく、透明度が維持された画像が作成されます。それは大規模なハックのままですが、少なくともこれらの行にもう我慢する必要はありません!

No lines and transparency

7
cako

試してみてください:

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

今では(私が見つけることができた)ウェブ上で十分に文書化されていますが、

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

matplotlib/lib/matplotlib/colorbar.pyから取得)drawedgesTrueに設定すると、それらの線を描画するように指示されていると思います。

1
tacaswell

他の提案はどれも私にはうまくいかなかったので、私はカラーバーインスタンスからアルファチャンネルを削除することになりました:

from matplotlib.colors import to_rgb

lut = colorbar.solids.get_facecolor()
bg_color = to_rgb('white')
lut[:, :3] *= lut[:, 3:]
lut[:, :3] += (1 - lut[:, 3:]) * bg_color
lut[:, 3] = 1.
colorbar.solids.set_facecolor(lut)

顔の色にアクセスするには、カラーバーを1回描画する必要がありました。

0

以下は、エレガントでなくても別の解決策になる可能性があります。

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)
0
Daewon Lee