代码之家  ›  专栏  ›  技术社区  ›  Peaceful

用matplotlib中的箭头绘制相空间轨迹

  •  13
  • Peaceful  · 技术社区  · 8 年前

    我试图画出某个动力系统的相空间图。实际上,我有一个2d平面,其中有一个起点,然后是下一个点,以此类推。我想用线连接这些点,在上面我想画一些箭头,这样我就可以看到方向(起点到下一点等)。我决定使用线型 '->' 但它并没有给出任何好的结果,箭头实际上似乎多次指向错误的方向。而且它们的间距非常近,因此我看不到单独的线条。

    我的代码如下:

    import numpy as np
    import matplotlib.pylab as plt
    from scipy.integrate import odeint
    
    def system(vect, t):
        x, y = vect
        return [x - y - x * (x**2 + 5 * y**2), x + y - y * (x**2 + y**2)]
    
    vect0 = [(-2 + 4*np.random.random(), -2 + 4*np.random.random()) for i in range(5)]
    t = np.linspace(0, 100, 1000)
    
    for v in vect0:
        sol = odeint(system, v, t)
        plt.plot(sol[:, 0], sol[:, 1], '->')
    
    plt.show()
    

    结果图如下所示: Phase plot

    可以看出,箭头没有与连接点的线正确对齐。此外,许多箭头都“向外”,我希望它们“进来”,因为下一个点总是指向中间的闭合环。此外,情节看起来太乱了,我想画更少的箭头,这样情节看起来会更好。有人知道怎么做吗?提前谢谢。

    1 回复  |  直到 8 年前
        1
  •  15
  •   rjkilpatrick tfv    4 年前

    我认为解决方案应该是这样的:

    enter image description here

    使用该代码:

    import numpy as np
    import matplotlib.pylab as plt
    from scipy.integrate import odeint
    from scipy.misc import derivative
        
    def system(vect, t):
        x, y = vect
        return [x - y - x * (x**2 + 5 * y**2), x + y - y * (x**2 + y**2)]
        
    vect0 = [(-2 + 4*np.random.random(), -2 + 4*np.random.random()) for i in range(5)]
    t = np.linspace(0, 100, 1000)
    
    color=['red','green','blue','yellow', 'magenta']
        
    plot = plt.figure()
        
    for i, v in enumerate(vect0):
        sol = odeint(system, v, t)
        plt.quiver(sol[:-1, 0], sol[:-1, 1], sol[1:, 0]-sol[:-1, 0], sol[1:, 1]-sol[:-1, 1], scale_units='xy', angles='xy', scale=1, color=color[i])    
    
    plt.show(plot)    
    

    [编辑:关于指数的一些解释:

    • 颤抖及其参数的定义可以在这里找到: https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.quiver
    • 这里可以找到颤抖的好例子: https://www.getdatajoy.com/examples/python-plots/vector-fields
    • quiver需要矢量作为输入,矢量由起点和终点定义(起点和终点基本上是sol中存储的线坐标中的点i和i+1)
    • 因此,矢量数组的长度将比坐标数组的长度短一倍
    • 为了补偿这一点,并为坐标和矢量提供相同长度的阵列,我们必须使用以下索引:
    • sol[:-1, 0] (:第一个索引中的-1将删除最后一个坐标)
    • sol[1:, 0] (1:在第一个索引中开始下降第一个坐标)
    • sol[1:, 0] - sol[:-1, 0] 因此,创建长度为n-1的两个向量并将其相减的一种简便方法是 sol[i+1] - sol[i]