Ellipse的Edgecolor作为第三个变量的函数

时间:2016-05-16 19:42:38

标签: python-3.x matplotlib ellipse

我希望椭圆的edgecolor是第三个变量的函数。让我们假设第三个变量叫做通量。如果变量' flux'的值很高,我希望椭圆的边缘颜色为深蓝色,如果值很低,我希望颜色为黄色。任何中间值都应该是这些颜色的混合。我希望这个颜色渐变在图的z轴上可见,具有最高和最低值。我尝试引用此链接Matplotlib scatterplot; colour as a function of a third variable,但这似乎并不适用于我的情况。我正在读取从文本文件中绘制椭圆所需的参数,如下所示:

149.20562 2.29594 0.00418 0.00310 83.40 1.15569 

149.23158 1.99783 0.00437 0.00319 90.30 3.46331 

149.23296 2.45440 0.00349 0.00264 120.30 2.15457 

第五列是名为' flux'必须根据其绘制颜色渐变。

这是我尝试的一个例子。

import matplotlib.pyplot as plt
import numpy as np
import math
import astropy.io.ascii as asciitable
from matplotlib.patches import Ellipse
ax = plt.gca()
path="/users/xxxx/Desktop/"
plt.xlim([149,151.3])
plt.ylim([1,3.3])
fw=open(path + 'data_plot.txt', 'r')
data = asciitable.read(path+ "data_plot.txt") 
np.array(data)
for i in range(len(data)):
    ra,dec,maj,minor,ang,flux =data[i][0],data[i][1],data[i][2],data[i][3],data[i][4],data[i][5]
    ellipse = Ellipse(xy=(ra, dec), width=maj, height=minor, angle=ang, edgecolor=flux, lw=3, fc='None')
    ax.add_patch(ellipse) 


plt.xlabel('Right Ascention')
plt.ylabel('Declination')
plt.title('abc') 
plt.savefig(path+'abc.eps')

正如所料,这并没有奏效。这是我的错误日志。

runfile('/users/vishnu/.spyder2-py3/radio_sources.py',   wdir='/users/vishnu/.spyder2-py3')


    Traceback (most recent call last):

  File "<ipython-input-695-a0011c0326f5>", line 1, in <module>
    runfile('/users/vishnu/.spyder2-py3/radio_sources.py', wdir='/users/vishnu/.spyder2-py3')

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 699, in runfile
    execfile(filename, namespace)

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 88, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "/users/vishnu/.spyder2-py3/radio_sources.py", line 63, in <module>
    ellipse = Ellipse(xy=(ra, dec), width=maj, height=minor, angle=ang, edgecolor=flux, lw=3, fc='None')

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/matplotlib/patches.py", line 1378, in __init__
    Patch.__init__(self, **kwargs)

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/matplotlib/patches.py", line 111, in __init__
    self.set_edgecolor(edgecolor)

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/matplotlib/patches.py", line 277, in set_edgecolor
    self._edgecolor = colors.colorConverter.to_rgba(color, self._alpha)

  File "/users/vishnu/anaconda3/lib/python3.5/site-packages/matplotlib/colors.py", line 376, in to_rgba
    'to_rgba: Invalid rgba arg "%s"\n%s' % (str(arg), exc))

ValueError: to_rgba: Invalid rgba arg "1.15569"
to_rgb: Invalid rgb arg "1.15569"
cannot convert argument to rgb sequence

1 个答案:

答案 0 :(得分:2)

您只需将flux的值更改为matplotlib颜色即可。我们可以使用色图来执行此操作,或者在您的情况下,您可以使用flux来定义颜色,假设有一些最小值和最大值。

由于黄色只是红色和绿色的混合,我们可以使用1减去R和G通道的归一化通量,并使用标准化通量作为RGB元组的B通道来制作matplotlib颜色。

# Change these based on your definition of a 'high' value and a 'low' value (or the min/max of the data)
minflux = data[:][5].min()
maxflux = data[:][5].max()

for i in range(len(data)):
    ra,dec,maj,minor,ang,flux =data[i][0],data[i][1],data[i][2],data[i][3],data[i][4],data[i][5]

    # Normalise the flux value to the range 0-1
    normflux = (flux - minflux) / (maxflux - minflux)
    # RGB tuple. This will be yellow for min value and blue for max value
    fluxcolor = (1.-normflux, 1.-normflux, normflux)

    ellipse = Ellipse(xy=(ra, dec), width=maj, height=minor, angle=ang, edgecolor=fluxcolor, lw=3, fc='None')
    ax.add_patch(ellipse) 

以下是检查其有效的最小示例:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import numpy as np

fig,ax = plt.subplots(1)

minflux = 0.
maxflux = 10.

for i in range(10):

    flux = float(i)

    normflux = (flux - minflux) / (maxflux - minflux)
    fluxcolor = (1.-normflux, 1.-normflux, normflux)

    ell = Ellipse(xy=(i+1,0.5), width=0.5, height=0.3, angle=90., edgecolor=fluxcolor, lw=3, fc='None')

    ax.add_patch(ell)

ax.set_xlim(0,11)
plt.show()

enter image description here

要添加颜色条,也许 最简单的方法是使用色彩映射而不是上面显示的方法。在这种情况下,我们还可以使用PatchCollection将所有椭圆添加到轴,然后将集合的数组设置为通量值以定义它们的颜色。

例如:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import numpy as np

import matplotlib.colors as colors
from matplotlib.collections import PatchCollection

# Define our colormap here. 
# Want red and green to be 1 at 0, and 0 at 1. Blue to be 0 at 0, and 1 at 1.
cdict = {'red':  ((0.0,1.0,1.0),
                  (1.0,0.0,0.0)),
        'green': ((0.0,1.0,1.0),
                  (1.0,0.0,0.0)),
        'blue':  ((0.0,0.0,0.0),
                  (1.0,1.0,1.0))
        }
# Use that dictionary to define the Linear SegmentedColormap
YlBu = colors.LinearSegmentedColormap('YlBu',cdict)

# Create figure
fig,ax = plt.subplots(1)

# Set the aspect ratio
ax.set_aspect('equal')

# We will populate these lists as we loop over our ellipses
ellipses = []
fluxes = []

for i in range(9):

    # Use i as a dummy value for our flux
    flux = float(i)

    # Store the fluxes. You have this already in your data array
    fluxes.append(flux)

    # Angle is in degrees
    angle = float(i) * 45.

    # Create the ellipse patch. Don't add to the axes yet
    ell = Ellipse(xy=(i,2.), width=0.8, height=0.2, angle=angle)

    # Just add it to this list
    ellipses.append(ell)

# Now, create a patch collection from the ellipses. 
# Turn off facecolor, and set the colormap to the one we created earlier
pc = PatchCollection(ellipses,False,lw=3,cmap=YlBu,facecolor='None')

# Set the color array here.
pc.set_array(np.array(fluxes))

# Now we add the collection to the axes
ax.add_collection(pc)

# And create a colorbar
fig.colorbar(pc,orientation='horizontal')

# Set the axes limits
ax.set_xlim(-1,9)
ax.set_ylim(0,4)

plt.show()

enter image description here