web-dev-qa-db-ja.com

Python / Matplotlibを使用して、カラーマップに基づいて(極)カラーホイールをプロットします

Pythonで、できればMatplotlibを使用してカラーホイールを作成しようとしています。以下は問題なく動作します:

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

xval = np.arange(0, 2*pi, 0.01)
yval = np.ones_like(xval)

colormap = plt.get_cmap('hsv')
norm = mpl.colors.Normalize(0.0, 2*np.pi)

ax = plt.subplot(1, 1, 1, polar=True)
ax.scatter(xval, yval, c=xval, s=300, cmap=colormap, norm=norm, linewidths=0)
ax.set_yticks([])

Own attempt at creating a color wheel

ただし、この試みには2つの重大な欠点があります。

最初に、結果の図をベクトル( figure_1.svg )として保存すると、カラーホイールは(予想どおり)プロットされるさまざまな(x、y)値に対応する621の異なる形状で構成されます。結果は円のように見えますが、実際にはそうではありません。いくつかのパスポイントとそれらの間のベジェ曲線で定義される実際の円を使用することを強くお勧めします。 matplotlib.patches.Circle 。これは私にとってそれを行う「適切な」方法のようであり、結果はより良く見えます(バンディングなし、より良いグラデーション、より良いアンチエイリアス)。

2番目に(関連して)、最後にプロットされたマーカー(2*piの前の最後のいくつか)は最初のいくつかと重なります。ピクセルレンダリングでは見づらいですが、ベクトルベースのレンダリングにズームインすると、最後のディスクが最初の数枚に重なっていることがはっきりとわかります。

別のマーカー(.または|)を使用してみましたが、2番目の問題を回避できませんでした。

結論:適切なベクトル/ベジェ曲線の方法で定義され、カラーマップに従って定義されたエッジの色(またはそれに失敗すると、任意の色のグラデーション)を持つ円をPython/Matplotlibで描画できますか?

17
EelkeSpaak

私が見つけた1つの方法は、カラーマップを作成し、それを極座標軸に投影することです。ここに実際の例があります-それは厄介なハックを含みます(明確にコメントされています)。制限を調整する方法、または自分でTransformを書いてそれを回避する方法は確かにあると思いますが、まだ完全には管理していません。 Normalizeの呼び出しの範囲でそれができると思いましたが、どうやらそうではありませんでした。

_import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
import matplotlib as mpl

fig = plt.figure()

display_axes = fig.add_axes([0.1,0.1,0.8,0.8], projection='polar')
display_axes._direction = 2*np.pi ## This is a nasty hack - using the hidden field to 
                                  ## multiply the values such that 1 become 2*pi
                                  ## this field is supposed to take values 1 or -1 only!!

norm = mpl.colors.Normalize(0.0, 2*np.pi)

# Plot the colorbar onto the polar axis
# note - use orientation horizontal so that the gradient goes around
# the wheel rather than centre out
quant_steps = 2056
cb = mpl.colorbar.ColorbarBase(display_axes, cmap=cm.get_cmap('hsv',quant_steps),
                                   norm=norm,
                                   orientation='horizontal')

# aesthetics - get rid of border and axis labels                                   
cb.outline.set_visible(False)                                 
display_axes.set_axis_off()
plt.show() # Replace with plt.savefig if you want to save a file
_

これにより

colorwheel direct from matplotlib

ホイールではなくリングが必要な場合は、plt.show()または_plt.savefig_の前にこれを使用してください。

_display_axes.set_rlim([-1,1])
_

これは与える

color ring


コメントの @ EelkeSpaak のとおり-OPに従ってグラフィックをSVGとして保存する場合、結果のグラフィックを操作するためのヒントを次に示します。結果のSVG画像の小さな要素は接触していて、非-重複。これにより、一部のレンダラー(Inkscape、Adobe Reader、おそらく印刷されていない)でかすかな灰色の線が表示されます。これに対する簡単な解決策は、たとえば、以下を使用して、個々のグラデーション要素のそれぞれに小さな(たとえば120%)スケーリングを適用することです。 InkscapeまたはIllustrator。図面全体ではなく、各要素に個別に変換を適用する必要があることに注意してください(前述のソフトウェアは、これを自動的に行う機能を提供します)。それ以外の場合、効果はありません。

15
J Richard Snape

カラーホイールを作成する必要があるだけで、rsnapeのソリューションを更新してmatplotlib 2.1と互換性があるようにしました。軸にカラーバーオブジェクトを配置する代わりに、極座標プロットに極カラーメッシュをプロットできます。

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

# If displaying in a Jupyter notebook:
# %matplotlib inline 

# Generate a figure with a polar projection
fg = plt.figure(figsize=(8,8))
ax = fg.add_axes([0.1,0.1,0.8,0.8], projection='polar')

# Define colormap normalization for 0 to 2*pi
norm = mpl.colors.Normalize(0, 2*np.pi) 

# Plot a color mesh on the polar plot
# with the color set by the angle

n = 200  #the number of secants for the mesh
t = np.linspace(0,2*np.pi,n)   #theta values
r = np.linspace(.6,1,2)        #radius values change 0.6 to 0 for full circle
rg, tg = np.meshgrid(r,t)      #create a r,theta meshgrid
c = tg                         #define color values as theta value
im = ax.pcolormesh(t, r, c.T,norm=norm)  #plot the colormesh on axis with colormap
ax.set_yticklabels([])                   #turn of radial tick labels (yticks)
ax.tick_params(pad=15,labelsize=24)      #cosmetic changes to tick labels
ax.spines['polar'].set_visible(False)    #turn off the axis spine.

それはこれを与えます:

A color wheel for the viridis colormap. Made with matplotlib 2.1.

7
toconnor