颜色条限制不考虑 plt.contourf 中的 vmin/vmax 设置.如何更明确地设置颜色条限制? [英] Colorbar limits are not respecting set vmin/vmax in plt.contourf. How can I more explicitly set the colorbar limits?

查看:26
本文介绍了颜色条限制不考虑 plt.contourf 中的 vmin/vmax 设置.如何更明确地设置颜色条限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用轮廓线f进行绘图时尝试调整数据范围时得到奇怪的结果

  import matplotlib将numpy导入为np将cmplotlib.cm导入为cm将matplotlib.mlab导入为mlab导入matplotlib.pyplot作为plt增量 = 0.025x = np.arange(-3.0,3.0,增量)y = np.arange(-2.0,2.0,delta)X,Y = np.meshgrid(x,y)Z1 = mlab.bivariate_normal(X,Y,1.0,1.0,0.0,0.0)Z2 = mlab.bivariate_normal(X,Y,1.5,0.5,1,1)# 高斯的差异Z = 10.0 * (Z2 - Z1)plt.figure()CS = plt.contourf(X, Y, Z, vmin = 0, vmax = 3)plt.title('最简单的默认标签')plt.colorbar()plt.show()

对我来说结果如下:

就像颜色与我设置的 vmin/vmax 匹配,但颜色栏上显示的数字范围仍然是未设置 vmin/vmax 时的样子.

在这种情况下,我希望最终结果的颜色条的范围是0到3.

解决方案

首先,标记为答案的响应是错误的(见我上面的评论),但帮助我想出了另外两个解决方案.

正如 JulianBauer 在下面的评论中指出的那样,OP 使用的函数 mlab.bivariate_normal 不再可用.为了提供产生可以与其他答案进行比较的输出的功能代码,我正在调用以下函数,并使用从

2.更复杂的解决方案

在上面的答案中提供,尽管它需要适应特定情况,并且很容易最终得到一个颜色条,其水平与实际情节中的水平不同.我发现这很危险,因此我尝试将其包装在可以在任何上下文中安全调用的函数中:

  def clippedcolorbar(CS,** kwargs):从matplotlib.cm导入ScalarMappablefrom numpy import arange, floor, ceil无花果= CS.ax.get_figure()vmin = CS.get_clim()[0]vmax = CS.get_clim()[1]m = ScalarMappable(cmap = CS.get_cmap())m.set_array(CS.get_array())m.set_clim(CS.get_clim())step = CS.levels[1] - CS.levels[0]cliplower = CS.zmin <vminclipupper = CS.zmax> vmaxnoextend = 'extend' in kwargs.keys() 和 kwargs['extend']=='neither'#设置颜色栏的边界boundary = arange((floor(vmin/step)-1 + 1 *(cliplower and noextend))* step,(ceil(vmax/step)+ 1-1 *(clipupper and noextend))* step,step)kwargs ['boundaries'] =边界# 如果 z 值超出颜色条范围,则添加扩展标记#可以通过向函数调用提供extend ='nether'来禁用此行为如果不是(在kwargs.keys()中为'extend')或在['min','max']中为kwargs ['extend']:extend_min = cliplower或(kwargs.keys()和kwargs ['extend'] =='min'中的'extend')extend_max = clipupper或(kwargs.keys()和kwargs ['extend'] =='max'中的'extend')如果extend_min 和extend_max:kwargs['extend'] = 'both'elif 扩展_分钟:kwargs ['extend'] ='min'elif 扩展_最大:kwargs['extend'] = 'max'返回 fig.colorbar(m, **kwargs)

函数中的主要命令与千焦耳在其回答中提出的内容相对应,但是需要更多的行才能通过从 contourf 对象中提取所有信息来避免所有显式的和潜在的错误分配.

用法:

OP 要求从 0 到 3 的级别.最深的蓝色代表低于 0 的值,因此我发现扩展标记很有用.

将 numpy 导入为 np导入 matplotlib将cmplotlib.cm导入为cm导入matplotlib.pyplot作为pltX,Y,Z = myfunction()plt.figure()plt.title('最简单的默认标签')CS = plt.contourf(X,Y,Z,等级= 6,vmin = 0.0,vmax = 3.0,cmap = cm.coolwarm)颜色条=裁剪的颜色条(CS)plt.show()

可以通过调用 clippedcolorbar(CS,extend ='noth')而不是 clippedcolorbar(CS)来禁用扩展标记.

Getting a strange result when trying to adjust the data range when plotting using contourf

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)

plt.figure()
CS = plt.contourf(X, Y, Z, vmin = 0, vmax = 3)
plt.title('Simplest default with labels')
plt.colorbar()

plt.show()

Results in this for me:

It's like the colors match the vmin/vmax I set, but the number range displayed on the colorbar remains what it would be without setting vmin/vmax.

In this case, I would like the end result to have a colorbar that ranges from 0 to 3.

解决方案

First of all, the response, marked as answer, is erroneous (see my comments above), but helped me to come up with two other solutions.

As JulianBauer pointed out in a comment below, the function mlab.bivariate_normal used by the OP is not available any more. To provide functional code that produces output that can be compared with the other answers I am calling the following function, with the definition of bivariate_normal copied from the matplotlib repository:

def myfunction():

    def bivariate_normal(X, Y, sigmax=1.0, sigmay=1.0, mux=0.0, muy=0.0, sigmaxy=0.0):
        """copied from here: https://github.com/matplotlib/matplotlib/blob/81e8154dbba54ac1607b21b22984cabf7a6598fa/lib/matplotlib/mlab.py#L1866"""
        Xmu = X-mux
        Ymu = Y-muy
        rho = sigmaxy/(sigmax*sigmay)
        z = Xmu**2/sigmax**2 + Ymu**2/sigmay**2 - 2*rho*Xmu*Ymu/(sigmax*sigmay)
        denom = 2*np.pi*sigmax*sigmay*np.sqrt(1-rho**2)
        return np.exp(-z/(2*(1-rho**2))) / denom

    delta = 0.025
    x = np.arange(-3.0, 3.0, delta)
    y = np.arange(-2.0, 2.0, delta)
    X, Y = np.meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)
    return X,Y,Z

1. A simple and straight forward solution

Make use of the extend command while providing custom levels:

import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt

X,Y,Z = myfunction()

plt.figure()
plt.title('Simplest default with labels')
levels = np.linspace(0.0, 3.0, 7)
CS = plt.contourf(X, Y, Z, levels=levels, cmap=cm.coolwarm, extend='min')

colorbar = plt.colorbar(CS)

plt.show()

2. A more complicated solution

is provided in the answer above, though it needs to be adapted to specific cases and one can easily end up with a colorbar whose levels differs from those in the actual plot. I find this dangerous, so I attempted to wrap it up in a function that can safely be called in any context:

def clippedcolorbar(CS, **kwargs):
    from matplotlib.cm import ScalarMappable
    from numpy import arange, floor, ceil
    fig = CS.ax.get_figure()
    vmin = CS.get_clim()[0]
    vmax = CS.get_clim()[1]
    m = ScalarMappable(cmap=CS.get_cmap())
    m.set_array(CS.get_array())
    m.set_clim(CS.get_clim())
    step = CS.levels[1] - CS.levels[0]
    cliplower = CS.zmin<vmin
    clipupper = CS.zmax>vmax
    noextend = 'extend' in kwargs.keys() and kwargs['extend']=='neither'
    # set the colorbar boundaries
    boundaries = arange((floor(vmin/step)-1+1*(cliplower and noextend))*step, (ceil(vmax/step)+1-1*(clipupper and noextend))*step, step)
    kwargs['boundaries'] = boundaries
    # if the z-values are outside the colorbar range, add extend marker(s)
    # This behavior can be disabled by providing extend='neither' to the function call
    if not('extend' in kwargs.keys()) or kwargs['extend'] in ['min','max']:
        extend_min = cliplower or ( 'extend' in kwargs.keys() and kwargs['extend']=='min' )
        extend_max = clipupper or ( 'extend' in kwargs.keys() and kwargs['extend']=='max' )
        if extend_min and extend_max:
            kwargs['extend'] = 'both'
        elif extend_min:
            kwargs['extend'] = 'min'
        elif extend_max:
            kwargs['extend'] = 'max'
    return fig.colorbar(m, **kwargs)

The main commands in the function correspond to what kilojoules proposes in his/her answer, but more lines are required to avoid all the explicit and potentially erroneous assignments by extracting all information from the contourf object.

Usage:

The OP asks for levels from 0 to 3. The darkest blue represents values below 0, so I find an extend-marker useful.

import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt

X,Y,Z = myfunction()

plt.figure()
plt.title('Simplest default with labels')
CS = plt.contourf(X, Y, Z, levels=6, vmin=0.0, vmax=3.0, cmap=cm.coolwarm)

colorbar = clippedcolorbar(CS)

plt.show()

The extend marker can be disabled by calling clippedcolorbar(CS, extend='neither') instead of clippedcolorbar(CS).

这篇关于颜色条限制不考虑 plt.contourf 中的 vmin/vmax 设置.如何更明确地设置颜色条限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆