渲染非均匀网格并在等高线图中标记最大值的位置

时间:2015-01-26 19:21:22

标签: python numpy matplotlib

matplotlib中的轮廓图有两个问题:

  1. 如何将任意网格网格渲染为常规网格网格?
  2. 我希望两个轴上的刻度位置均匀分布,同时仍能反映节点的位置。

    1. 如何使用彩色标记突出显示数据的最高值位置?
    2. enter image description here

      这是我的代码:

      import numpy as np
      import pylab as pl
      
      def plot_s(data, xlist, ylist):
      
          pl.subplot(111)
          x = np.array(xlist)
          y = np.array(ylist)
          X, Y = np.meshgrid(x, y)
          CS = pl.contour(X, Y, data, colors='k')
          pl.clabel(CS, inline = 1, fontsize=10)
          pl.xlabel('x list')
          pl.ylabel('y list')
          pl.xticks(xlist)
          pl.yticks(ylist)
          pl.title('Contour plot')
          pl.show()
      
      def main():
      
          data = np.array([[ 0.56555019,  0.57933922,  0.58266252,  0.58067285,  0.57660236, 0.57185625,  0.56711252,  0.55557035,  0.55027705,  0.54480605],
                           [ 0.55486559,  0.57349717,  0.57940478,  0.57843897,  0.57463271, 0.56963449,  0.5643922 ,  0.55095598,  0.54452534,  0.53762606],
                           [ 0.53529358,  0.56254991,  0.57328105,  0.57409218,  0.57066168, 0.5654082 ,  0.55956853,  0.5432474 ,  0.53501127,  0.52601203],
                           [ 0.50110483,  0.54004071,  0.55800178,  0.56173719,  0.55894846, 0.55328279,  0.54642887,  0.52598388,  0.51533094,  0.50354147]])
      
          xlist =  [10., 20., 30., 40., 50., 60., 70., 100., 120., 150.]
          ylist =  [50, 70, 90, 100]
          plot_s(data, xlist, ylist)
      
      if __name__ == '__main__':
          main()
      

2 个答案:

答案 0 :(得分:1)

  1. 如何将任意网格网格渲染为常规网格网格?
  2. 一个建议是创建一个常规的网格网格,首先在最小和最大x和y之间创建均匀间隔值的数组。此外,您可以使用自定义刻度来反映您的数据点不等距的事实。请参阅代码中的注释,了解我是如何实现的。

    1. 如何使用彩色标记突出显示数据最高值的位置?
    2. 要检索最高值,您可以使用np.max(),然后使用np.where在数据数组中查找此值的位置。只需在此位置绘制标记即可。

      或者,使用plt.contour,你可以创建一个水平,其水平足够接近你的最大值的位置,在它周围创建一个环,甚至是它上面的一个点:

      epsillon = 0.0001
      levels = np.arange(max_value - epsillon, max_value + epsillon)
      CS2 = plt.contour(X,Y,data, levels,
                   origin='lower',
                   linewidths=2,
                   extent=(-3,3,-2,2))
      

      请注意,使用第一种方法时,点将最终位于现有网格节点的顶部,而plt.contour会插入数据,并且根据使用的插值算法,可能会导致位置略有不同。然而在这里似乎同意。

      代码:

      import numpy as np
      import matplotlib.pyplot as plt 
      import matplotlib
      
      def plot_s(data, x, y, xlist, ylist):
          ax = plt.gca()
      
          ###########  create your uniform meshgrid.....   ############
          X, Y = np.meshgrid(x, y)
          CS = ax.contour(X, Y, data, colors='k')
      
          ###### ... and let ticks indicate that your new space is not linear  
          # assign tick positions according to the regular array
          ax.set_yticks(y)
          # Assign the label to reflect your original nodes position
          ax.set_yticklabels(ylist)
      
          # and same for x
          ax.set_xticks(x)
          ax.set_xticklabels(xlist)
          #############################################################
      
      
          ###########    GET MAXIMUM AND MARK IT WITH A POINT  ########
          # get maximum value in your data
          max_value = np.max(data)
          # get position index of this calue in your data array 
          local_max_index = np.where(data==max_value)
      
          ## retrieve position of your
          max_x = X[local_max_index[0], local_max_index[1]]
          max_y = Y[local_max_index[0], local_max_index[1]]
      
          # plot one marker on this position
          plt.plot(max_x, max_y, color="red", marker = "o", zorder = 10, 
                                             markersize=15, clip_on=False)
          ##############################################################
      
          plt.title('Contour plot')
          plt.show()
      
      
      def main():
          # Your data: 4 x 10 array
          data = np.array([[ 0.56555019,  0.57933922,  0.58266252,  0.58067285, 0.57660236,
                             0.57185625,  0.56711252,  0.55557035,  0.55027705,  0.54480605],
                           [ 0.55486559,  0.57349717,  0.57940478,  0.57843897,  0.57463271,
                             0.56963449,  0.5643922 ,  0.55095598,  0.54452534,  0.53762606],
                           [ 0.53529358,  0.56254991,  0.57328105,  0.57409218,  0.57066168,
                             0.5654082 ,  0.55956853,  0.5432474 ,  0.53501127,  0.52601203],
                           [ 0.50110483,  0.54004071,  0.55800178,  0.56173719,  0.55894846,
                             0.55328279,  0.54642887,  0.52598388,  0.51533094,  0.50354147]])
          # create a list values with regular interval for the mesh grid
          x = np.array([10 + i * (150.-10.)/9 for i in range(10)])
          y = np.array([50 + i * (100.-50.)/4 for i in range(4)])
      
          # create arrays with values to be displayed as ticks    
          xlist =  np.array([10., 20., 30., 40., 50., 60., 70., 100., 120., 150.])
          ylist =  np.array([50, 70, 90, 100])
      
          plot_s(data, x, y, xlist, ylist)
      
      if __name__ == '__main__':
          main()
      

      瞧:

      这里使用背景中的meshgrid来显示变形/映射:

答案 1 :(得分:1)

下面基本上是相同的,但是由snake_charmer提出的稍微更紧凑的版本。但是,我不确定我是否正确理解了您的问题。如果xlistylist中的点数不是太不规则间隔,则更优雅的解决方案可能是保留不规则网格,但使用ax.grid()突出显示数据点的位置。这取决于你想在图中显示的确切内容。

import numpy as np
from matplotlib import pyplot as plt

def plot_s(data, xlist, ylist):

    fig, ax = plt.subplots()
    x = np.arange(len(xlist))
    y = np.arange(len(ylist))
    X, Y = np.meshgrid(x, y)
    CS = ax.contour(X, Y, data, colors='k')
    ax.clabel(CS, inline = 1, fontsize=10)
    ax.set_xlabel('x list')
    ax.set_ylabel('y list')
    ax.set_xticks(x)
    ax.set_yticks(y)
    ax.set_xticklabels(xlist)
    ax.set_yticklabels(ylist)

    jmax, imax = np.unravel_index(np.argmax(data), data.shape)
    ax.plot(imax, jmax, 'ro')

    ax.set_title('Contour plot')
    plt.show()

def main():

    data = np.array([[ 0.56555019,  0.57933922,  0.58266252,  0.58067285,
                       0.57660236,  0.57185625,  0.56711252,  0.55557035,
                       0.55027705,  0.54480605],
                     [ 0.55486559,  0.57349717,  0.57940478,  0.57843897,
                       0.57463271,  0.56963449,  0.5643922 ,  0.55095598,
                       0.54452534,  0.53762606],
                     [ 0.53529358,  0.56254991,  0.57328105,  0.57409218,
                       0.57066168,  0.5654082 ,  0.55956853,  0.5432474 ,
                       0.53501127,  0.52601203],
                     [ 0.50110483,  0.54004071,  0.55800178,  0.56173719,
                       0.55894846,  0.55328279,  0.54642887,  0.52598388,
                       0.51533094,  0.50354147]])

    xlist =  [10., 20., 30., 40., 50., 60., 70., 100., 120., 150.]
    ylist =  [50, 70, 90, 100]
    plot_s(data, xlist, ylist)

if __name__ == '__main__':
    main()