首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何绘制温度计?

如何绘制温度计?
EN

Stack Overflow用户
提问于 2019-02-20 15:58:50
回答 1查看 1.2K关注 0票数 5

在最近的一个非常广泛的问题中,有人问它如何用matplotlib绘制几个符号,比如“圆圈、正方形、矩形、星星、温度计和盒子图”。从这个列表中可以看出,除了温度计之外,所有的温度计都是显而易见的,无论是在文档中还是在许多现有的堆栈溢出答案中。因为这个实验看起来对热电偶一点也不感兴趣,所以我想问一个关于温度计的新问题。

如何在matplotlib中绘制温度计?

原则上,您可以绘制任何您喜欢的符号,使其成为markerPath。不过,似乎没有任何用于温度计的unicode符号。字体超赞有一个温度计符号,并在matplotlib 是可能的中绘制FontAwesome符号。但只有5种不同的填充物

此外,这种字体符号的颜色是一致的,但理想的情况是,温度计的内部部分(“水银柱”)以不同的颜色(可能主要是红色,因为联想原因)或以不同的颜色编码温度的颜色。

那么,有可能有一个温度符号,其中的水银柱编码温度(或事实上任何其他数量)的颜色和填充水平?如果是,怎么做?

(我在下面给出了一个答复,欢迎替代或改进这种方法,作为这里的进一步答案。)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-20 15:58:50

绘制由两个部分组成的温度计的一个选项是创建两个Paths,外壳和内水银柱。为此,可以从头创建路径,并根据(规范化)输入参数允许内部路径是可变的。

然后将这两条路径绘制成单独的散点图是可能的。在下面的示例中,我们创建了一个具有scatter方法的类,它的工作方式类似于通常的scatter,但它也将使用温度的附加参数temp和用于温度正常化的tempnorm作为输入。

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.path as mpath

class TemperaturePlot():

    @staticmethod
    def get_hull():
        verts1 = np.array([[0,-128],[70,-128],[128,-70],[128,0],
                          [128,32.5],[115.8,61.5],[96,84.6],[96,288],
                          [96,341],[53,384],[0,384]])
        verts2 = verts1[:-1,:] * np.array([-1,1])
        codes1 = [1,4,4,4,4,4,4,2,4,4,4]
        verts3 = np.array([[0,-80],[44,-80],[80,-44],[80,0],
                          [80,34.3],[60.7,52],[48,66.5],[48,288],
                          [48,314],[26.5,336],[0,336]])
        verts4 = verts3[:-1,:] * np.array([-1,1])
        verts = np.concatenate((verts1, verts2[::-1], verts4, verts3[::-1]))
        codes = codes1 + codes1[::-1][:-1]
        return mpath.Path(verts/256., codes+codes)

    @staticmethod
    def get_mercury(s=1):
        a = 0; b = 64; c = 35
        d = 320 - b
        e = (1-s)*d
        verts1 = np.array([[a,-b],[c,-b],[b,-c],[b,a],[b,c],[c,b],[a,b]])
        verts2 = verts1[:-1,:] * np.array([-1,1])
        verts3 = np.array([[0,0],[32,0],[32,288-e],[32,305-e],
                           [17.5,320-e],[0,320-e]])
        verts4 = verts3[:-1,:] * np.array([-1,1])
        codes = [1] + [4]*12 + [1,2,2,4,4,4,4,4,4,2,2]
        verts = np.concatenate((verts1, verts2[::-1], verts3, verts4[::-1]))
        return mpath.Path(verts/256., codes)

    def scatter(self, x,y, temp=1, tempnorm=None, ax=None, **kwargs):
        self.ax = ax or plt.gca()
        temp = np.atleast_1d(temp)
        ec = kwargs.pop("edgecolor", "black")
        kwargs.update(linewidth=0)
        self.inner = self.ax.scatter(x,y, **kwargs)
        kwargs.update(c=None, facecolor=ec, edgecolor=None, color=None)
        self.outer = self.ax.scatter(x,y, **kwargs)
        self.outer.set_paths([self.get_hull()])
        if not tempnorm:
            mi, ma = np.nanmin(temp), np.nanmax(temp)
            if mi == ma:
                mi=0
            tempnorm = plt.Normalize(mi,ma)
        ipaths = [self.get_mercury(tempnorm(t)) for t in temp]
        self.inner.set_paths(ipaths)

这个类的用法可能如下所示,

代码语言:javascript
复制
plt.rcParams["figure.figsize"] = (5.5,3) 
plt.rcParams["figure.dpi"] = 72*3

fig, ax = plt.subplots()
p = TemperaturePlot()
p.scatter([.25,.5,.75], [.3,.4,.5], s=[800,1200,1600], temp=[28,39,35], color="C3",
          ax=ax, transform=ax.transAxes)

plt.show()

在这里,我们用“水银”柱的填充所描绘的不同温度绘制了3个温度计。由于不给出归一化,它将使[28,39,35]的温度在最小值和最大值之间正常化。

或者我们可以使用颜色(c)和temp来显示温度,如

代码语言:javascript
复制
np.random.seed(42)
fig, ax = plt.subplots()
n = 42
x = np.linspace(0,100,n)
y = np.cumsum(np.random.randn(n))+5

ax.plot(x,y, color="darkgrey", lw=2.5)

p = TemperaturePlot()
p.scatter(x[::4],y[::4]+3, s=300, temp=y[::4], c=y[::4], edgecolor="k", cmap="RdYlBu_r")

ax.set_ylim(-6,18)
plt.show()

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54790467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档