Python | 解决cmaps库报错的问题

cmaps

作为曾经地球科学领域最炙手可热脚本语言之一的NCL已经进入维护模式,不再更新。Python中的cmaps库提供了560条来自NCL的colorbar,使得我们可以在Python绘制出和NCL中一样的colorbar。

例图展示

在气象研究中,一个好看的colorbar可以让你的学术图表填色不少,如下面几张图。

NCL Colorbar查询

NCL的colorbar可在该网址中查询:https://www.ncl.ucar.edu/Document/Graphics/color_table_gallery.shtml

cmaps库GitHub网址:https://github.com/hhuangwx/cmaps

有喜欢的colorbar可通过以上两个网址中查询。

cmaps库colorbar大全

cmaps库colorbar大全

绘制以上图片的代码如下:
import cmaps
import numpy as np
import inspect

import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc('text', usetex=False)


def list_cmaps():
    attributes = inspect.getmembers(cmaps, lambda _: not (inspect.isroutine(_)))
    colors = [_[0] for _ in attributes if
              not (_[0].startswith('__') and _[0].endswith('__'))]
    return colors


if __name__ == '__main__':
    color = list_cmaps()

    a = np.outer(np.arange(0, 1, 0.001), np.ones(10))
    plt.figure(figsize=(20, 20))
    plt.subplots_adjust(top=0.95, bottom=0.05, left=0.01, right=0.99)
    ncmaps = len(color)
    nrows = 8
    for i, k in enumerate(color):
        plt.subplot(nrows, ncmaps // nrows + 1, i + 1)
        plt.axis('off')
        plt.imshow(a, aspect='auto', cmap=getattr(cmaps, k), origin='lower')
        plt.title(k, rotation=90, fontsize=10)
        plt.title(k, fontsize=10)
    plt.savefig('colormaps.png', dpi=300)
注意:

以上代码在Python3.9-3.10或者更高的版本中可能报错,这个问题也是我们今天推文需要解决的问题。

cmaps库的报错

报错内容

这里我们以BlueWhiteOrangeRedcolobar为例,在最近使用cmaps库会出现报错:

ValueError: A colormap named "BlueWhiteOrangeRed" is already registered.

接下来我们将解决这个问题。

解决cmaps报错问题

cmaps库的实现原理:

cmaps库的实现原理其实不难,通过下载NCL官网中的所有colormap的rgb文件使用正则表达式解析其中的 RGB 值,并将其转换为 Matplotlib 可以识别的颜色映射对象。最后将颜色映射对象被注册到 Matplotlib 的注册表中,我们可以直接调用这些映射进行绘图。

BlueWhiteOrangeRed colormap

BlueWhiteOrangeRed colormap

cmaps库源码部分展示

cmaps库源码部分展示

解决方案

从以上源码可以看出,cmaps库创建了一个Cmaps的类,将BlueWhiteOrangeRed定义为Cmaps类中的一个方法,而报错内容:ValueError: A colormap named "BlueWhiteOrangeRed" is already registered.,则是告诉我们BlueWhiteOrangeRed的colormap已经被注册。

使用以下代码将解决以上的问题:

import matplotlib.pyplot as plt
import cmaps
def register_cmap_if_needed(cmap_name, cmap_module):
    try:
        cmap_object = getattr(cmap_module, cmap_name)
        if cmap_name not in plt.colormaps():
            plt.register_cmap(cmap=cmap_object, name=cmap_name)
    except:
        pass

cmap_name = "WhiteBlueGreenYellowRed"
register_cmap_if_needed(cmap_name, cmaps)

根据源码,我们使用Python的内置函数getattr 获取对象的属性,从而避免colorbar的重复注册,从而解决问题。

以上代码的伪代码为:

函数 注册颜色映射(颜色映射名称, 颜色映射模块):
    尝试:
        获取颜色映射对象,通过 颜色映射名称 从 颜色映射模块 中获取
        如果 颜色映射名称 不在当前已注册的颜色映射列表中:
            注册颜色映射,使用 颜色映射对象 和 颜色映射名称
    如果发生异常:
        忽略异常并继续执行

定义 颜色映射名称 为 "WhiteBlueGreenYellowRed"
调用 注册颜色映射 函数,传入 颜色映射名称 和 颜色映射模块
使用建议:

每次绘图需要运行一次以上代码,可以将以上代码复制到代码的最上方,需要修改colorbar时,只需要修改cmap_name即可。

使用例子

import matplotlib.pyplot as plt
import cmaps
def register_cmap_if_needed(cmap_name, cmap_module):
    try:
        cmap_object = getattr(cmap_module, cmap_name)
        if cmap_name not in plt.colormaps():
            plt.register_cmap(cmap=cmap_object, name=cmap_name)
    except:
        pass

cmap_name = "WhiteBlueGreenYellowRed"
register_cmap_if_needed(cmap_name, cmaps)
...
...
(中间省略)
...
...
contourf_plot = plt.contourf(lon, lat, sst, cmap="WhiteBlueGreenYellowRed")

往期回顾

·投稿或转载请联系· 

长按可关注

长按可关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值