使用Pyx绘制大括号
我该如何用Pyx在两个任意点之间画一条“带支撑”的线呢?
它看起来会像这样:
支撑线示例 http://tof.canardpc.com/view/d16770a8-0fc6-4e9d-b43c-a11eaa09304d
2 个回答
5
tom10 提供了一个不错的解决方案,但还有改进的空间。
关键是要在范围 [0,1],[0,1] 上创建一个框架,然后进行缩放。
这个版本还允许你稍微调整形状。为了增加难度,它使用了二阶导数来决定点之间的间距。
mid
用来设置上下部分的平衡。
beta1
和 beta2
控制曲线的尖锐程度(上下部分)。
你可以改变 height
(或者直接把 y 值乘以一个数)。
如果想让它竖着显示,只需要交换 x 和 y 的位置。
initial_divisions
和 resolution_factor
决定了 x 值是怎么选择的,但一般来说可以忽略不计。
import numpy as NP
def range_brace(x_min, x_max, mid=0.75,
beta1=50.0, beta2=100.0, height=1,
initial_divisions=11, resolution_factor=1.5):
# determine x0 adaptively values using second derivitive
# could be replaced with less snazzy:
# x0 = NP.arange(0, 0.5, .001)
x0 = NP.array(())
tmpx = NP.linspace(0, 0.5, initial_divisions)
tmp = beta1**2 * (NP.exp(beta1*tmpx)) * (1-NP.exp(beta1*tmpx)) / NP.power((1+NP.exp(beta1*tmpx)),3)
tmp += beta2**2 * (NP.exp(beta2*(tmpx-0.5))) * (1-NP.exp(beta2*(tmpx-0.5))) / NP.power((1+NP.exp(beta2*(tmpx-0.5))),3)
for i in range(0, len(tmpx)-1):
t = int(NP.ceil(resolution_factor*max(NP.abs(tmp[i:i+2]))/float(initial_divisions)))
x0 = NP.append(x0, NP.linspace(tmpx[i],tmpx[i+1],t))
x0 = NP.sort(NP.unique(x0)) # sort and remove dups
# half brace using sum of two logistic functions
y0 = mid*2*((1/(1.+NP.exp(-1*beta1*x0)))-0.5)
y0 += (1-mid)*2*(1/(1.+NP.exp(-1*beta2*(x0-0.5))))
# concat and scale x
x = NP.concatenate((x0, 1-x0[::-1])) * float((x_max-x_min)) + x_min
y = NP.concatenate((y0, y0[::-1])) * float(height)
return (x,y)
使用起来很简单:
import pylab as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x,y = range_brace(0, 100)
ax.plot(x, y,'-')
plt.show()
PS:别忘了可以在 plot
中传入 clip_on=False
,这样就可以把它放在坐标轴外面。
11
你可以用S型曲线来画漂亮的花括号。我没有安装Pyx,所以我就用matplotlib(这里用的是pylab)来画这些。这里的beta
控制着花括号曲线的尖锐程度。
import numpy as nx
import pylab as px
def half_brace(x, beta):
x0, x1 = x[0], x[-1]
y = 1/(1.+nx.exp(-1*beta*(x-x0))) + 1/(1.+nx.exp(-1*beta*(x-x1)))
return y
xmax, xstep = 20, .01
xaxis = nx.arange(0, xmax/2, xstep)
y0 = half_brace(xaxis, 10.)
y = nx.concatenate((y0, y0[::-1]))
px.plot(nx.arange(0, xmax, xstep), y)
px.show()
我把这个图沿着x轴画是为了节省屏幕空间,但如果想要沿着y轴画花括号,只需要把x和y互换就可以了。最后,Pyx里面有很多内置的路径绘制功能,也可以满足你的需求。