简体   繁体   English

对数比例 Matplotlib PatchCollection 颜色

[英]Log Scale Matplotlib PatchCollection Colors

I have a function that generates a heterogeneous mesh and then plots the patches.我有一个生成异构网格然后绘制补丁的函数。 It specifies the lower and upper x and y edge for every bin.它指定每个 bin 的上下xy边缘。 For example, a single bin is defined by the vector [x0, x1, y0, y1] .例如,单个 bin 由向量[x0, x1, y0, y1] These coordinates translate to a bin:这些坐标转换为一个 bin:

    y1|---------|   
      |         |  
      |   bin   | 
      |         |
    y0|---------|
     x0         x1   

I have an (Nx4) mesh that contains N bins with [x0, x1, y0, y1] columns.我有一个(Nx4) mesh ,其中包含N带有[x0, x1, y0, y1]列的 bin。 To plot the data, I do the following:为了绘制数据,我执行以下操作:

z_plot  = z_stat / (dx * dy)     # ``z_stat`` is a calculated z-value 
z_plot  = z_plot / z_plot.max()  # for any given bin.

colors = mpl.cm.jet(z_plot)                   # Let fill data be white.
colors[z_stat == fill] = (1.0, 1.0, 1.0, 1.0) # fill=-9999.0, typically.

dx = mesh[:, 1] - mesh[:, 0]  # x1-x0
dy = mesh[:, 3] - mesh[:, 2]  # y1-y0.

xy = zip(mesh[:, 0], mesh[:, 2])  # (x,y) coordinates of each
                                  # bin's lower left corner.

patches = [mpl.patches.Rectangle(xy[i], dx[i], dy[i],         # I dont want
                                 ec=None, lw=0, fc=colors[i]) # visible edges.
            for i in range(mesh.shape[0])
          ]

patches = mpl.collections.PatchCollection(patches, match_original=True)
ax.add_collection(patches)

if z_stat is not None:

    kwargs = {'orientation': 'vertical'}
    cax, kw = _mpl.colorbar.make_axes_gridspec(plot_ax, **kwargs)

    cbar = mpl.colorbar.ColorbarBase(cax, cmap=_mpl.cm.jet)

This is the result:这是结果:

<code>x</code> 和 <code>y</code> 数据被转换为 <code>y vs. x</code> 中的标准二维直方图。生成螺旋网格。 <code>Binned Data</code> 是每个 bin 中的数据点数。 <code>Bin Mean</code> 是 bin 中的平均值。对此进行日志缩放将非常有用。

This question does something similar, but without the logscale colors . This question做了类似的事情,但没有对数颜色 I don't know how to get the colors to log scale.我不知道如何将颜色设置为对数刻度。 Simply passing something like mpl.colors.LogNorm() to mpl.colorbar.ColorbarBase() did not work for me.简单地将mpl.colors.LogNorm()类的东西传递给mpl.colorbar.ColorbarBase()对我不起作用。

EDIT 1 : Generating the mesh.编辑 1 :生成网格。

I have a function that generates a heterogeneous mesh and then plots the patches.我有一个生成异构网格然后绘制补丁的函数。 It starts with a 2D array:它从一个二维数组开始:

mesh = [[x00, x10, y00, y01], 
        [x10, x11, y10, y11], 
        ..., 
        [xN0, xN1, yN0, yN1]] 

I read through the mesh and divide each bin in four:我通读了网格并将每个垃圾箱分成四个:

#    y1|----|----|          x0, x1, y0, y1 = mesh[i, :]
#      | p4 | p3 |          xh = [x0 + .5*(x1-x0)]
#      |----|----| <- yh    yh = [y0 + .5 *(y1-y0)]
#      | p1 | p2 |
#    y0|----|----|
#     x0    ^-xh x1       

If each of [p1, p2, p3, p4] have more than the minimum number of data points (eg 50), I replace row [x0, x1, y0, y1] with this array:如果[p1, p2, p3, p4]都有超过最小数量的数据点(例如 50),我用这个数组替换行[x0, x1, y0, y1]

        new_mesh = _np.array([[x0, xh, xh, x0],  # Define the 16 edges of  
                              [xh, x1, x1, xh],  # the 4 new bins that are  
                              [y0, y0, yh, yh],  # going to replace the bin 
                              [yh, yh, y1, y1]]  # originally defined by 
                            ).T                  # [x0, x1, y0, y1].

        if i == 0:  # 0th edge is a special case for indexing.

            mesh_h = _np.concatenate([new_mesh, mesh[1:]])

        else:

            mesh_h = _np.concatenate([mesh[:i], new_mesh, mesh[i+1:]])         


        mesh = mesh_h  # Set the new edges.

Although I can't test your exact case as you've not provided an independently runnable example you should (if my understanding of your desired behaviour is correct) be able to accomplish what you want as follows.尽管我无法测试您的确切情况,因为您没有提供独立的可运行示例,但您应该(如果我对您所需行为的理解是正确的)能够按如下方式完成您想要的操作。

Firstly edit this line to remove the manual setting of the colour and edge information:首先编辑这一行,去掉手动设置颜色和边缘信息:

patches = [mpl.patches.Rectangle(xy[i], dx[i], dy[i],         # I dont want
                                 ec=None, lw=0, fc=colors[i]) # visible edges.
            for i in range(mesh.shape[0])
          ]

It should look something like this:它应该是这样的:

patches = [mpl.patches.Rectangle(xy[i], dx[i], dy[i]) for i in range(mesh.shape[0])]

Then pass LogNorm , jet and your edge parameter to PatchCollection .然后将LogNormjet和您的边缘参数传递给PatchCollection This is because we want matplotlib to handle as much as possible by itself so it can sort out the colours for you.这是因为我们希望 matplotlib 自己处理尽可能多的事情,以便它可以为您整理颜色。

patch_collection = mpl.collections.PatchCollection(patches,cmap=matplotlib.cm.jet, norm=matplotlib.colors.LogNorm(), lw=0)

Then use set_array to give the PatchCollection the z information:然后使用set_arrayset_array提供 z 信息:

patch_collection.set_array(z_plot)

Finally add the collection to the plot, create the colorbar and show the figure:最后将集合添加到绘图中,创建颜色条并显示图形:

ax.add_collection(patch_collection)
plt.colorbar(patch_collection)

plt.show()

This answer is heavily based on the example given here which may be useful.这个答案很大程度上基于此处给出的示例这可能很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM