请选择 进入手机版 | 继续访问电脑版
爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 18271|回复: 4

[源代码] 永久导入自定义colormap随时调用

[复制链接]

新浪微博达人勋

发表于 2021-8-8 19:41:12 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 相雨书 于 2021-8-8 19:49 编辑

气象家园里大佬开发的cmaps模块很实用,ncl里的众多colormap都嵌入其中,调用起来也简单方便。

但有一次我在ncl官网中看到漂亮心仪的色标,在cmaps中调用时显示不存在。看来当前ncl官网中的colormap并不是全部导入进了cmaps。

此外,对于论文作图来说。每个人有每个人的绘图风格。对不同变量进行绘图处理也需要选择合适的colormap。已有的ncl提供的colormap固然种类繁多,但在实际使用中,待绘成变量场后发现实际上并不美观。
大多时候我需要进一步处理把colormap两段深色的部分截去,留下中间亮色部分,这样做出来的图像会更鲜亮,吸引人的眼球。

QQ截图20210807122307.jpg

再看看这些命名,复杂难记,有些并不直观反映内容。而且编程时你得一边开着编辑器,一边开着网页,挨个审阅哪个好看一些。试了一个发现不好看,继续试下一个。归根结底,你对这些colormap不熟悉。

这样就涉及到自定义colormap的调用问题。自定义的colormap可以是自己插值而来、从已有的ncl库中截取拼接而来,或者在看论文时,发现一个特别漂亮的图像,把别人的色标提取而来。

QQ截图20210807122704.jpg

总之,自定义colormap的有时比直接调用库colormap更方便美观。
如果要调用自定义的colormap,就需要在作图代码前先制作好rgb序列。 如果每次编程前都要复制这么三五行甚至十几行用来自定义colormap的代码是不是非常麻烦

有没有办法能把制作好的colormap永久性地存入库中,像cmaps和matplotlib一样使用时直接输入色标名就可以调用呢?

matplotlib有一个register_cmap()函数。顾名思义,它功能就是可以把自定义的colormap存入matplotlib已有的库中,并赋予色标名。调用时用法同matplotlib内置colormap。

但是非常遗憾,当我兴冲冲地制作好一个colormap并命名为"mycolor"后。调用一下,嗯,果然可用。可是第二天重新打开电脑,"mycolor"就不存在了。当你关闭编辑器(spyder,pycharm等),再重新打开,使用register_cmap()导入的colormap就清除了。你得重新导入一次,这仍然是一种极为麻烦的方式。

于是,我寻找另外一种方法,既然cmaps已经为我们开发好了一个巨大的库,我们为什么不好好利用它呢?
其实解决一次性永久导入自定义colormap的方法很简单,就是寻着cmaps存储rgb文件的轨迹,添加入我们自己的文件。

首先你得安装了cmaps库,但是先不要import它。
先找到它的安装路径

    # 获取cmaps模块安装路径  
    path = imp.find_module("cmaps")[1]

    # rgb文件路径
    if not isinstance(colormap, str):
        rgbdata = np.array(colormap)
    else:
        rgbdata = np.genfromtxt(colormap, delimiter = ' ', dtype = int, skip_header = 2, comments = '#')
    icmap=colors.ListedColormap(rgbdata)


colormap是你制作好的rgb序列。它可以是自定义的N*3的列表、元组或numpy array格式(RGB范围:0~255)。还可以是ncl官网直接下载的txt文件路径字符串,还可以是气象家园调色盘调色盘输出的ncl文件路径字符串(注意选择输出ncl格式的)。
然后将RGB和cmaps已有的RGB文件存在一起

mapsave = path+'\\colormaps\\self_defined\\'+colorname+'.rgb'
header = 'ncolors = '+str(rgbdata.shape[0])+'\n'+'  r   g   b'
np.savetxt(mapsave, rgbdata, header = header, delimiter = ' ', fmt = '%4d')


colorname是输入参数,为你自定义的colormap的名称
最后把相关信息写入

    f=open(path + '\\cmaps.py', 'a')

    add=['\n\n    @property',
         '\n    def '+colorname+'(self):',
         '\n        cname = '+'"'+colorname+'"',
         '\n        cmap_file = os.path.join(CMAPSFILE_DIR, "self_defined",  '+'"'+colorname+'.rgb")',
         '\n        cmap = Colormap(self._coltbl(cmap_file), name=cname)',
         '\n        matplotlib.cm.register_cmap(name=cname, cmap=cmap)',
    f2=open(path + '\\cmaps.py', 'r')
    count = 0
    for line in f2:
        if 'def '+colorname+'(self):' in line:
            count+=1
    f2.close()
    if count<1:
        f.writelines(add)
    f.close()


再给大家写一个离散颜色插值到渐变颜色,自定义的colormap。同时演示一下函数用法

import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
import colorimport

colormap = [(1, 0, 0), # 红
            (1,0, 1),  # 紫
            (0, 0, 1)] # 蓝

cm = LinearSegmentedColormap.from_list(
    'name',  
    colormap,  
    N = 100)

icmap=colregister('testcolors',255*cm(np.linspace(0,1,100)))

N = 100
x = np.linspace(-3.0, 3.0, N)
y = np.linspace(-2.0, 2.0, N)

X, Y = np.meshgrid(x, y)
fig, ax = plt.subplots()
cs = ax.contourf(np.sin(X)+np.cos(Y),levels=100, cmap=icmap)
fig.colorbar(cs)


QQ截图20210807125338.jpg

上面这个脚本对红、紫、蓝之间进行插值,生成连续的colormap,并给它一个名字“testcolors”。之后调用我们写的colregister函数,将刚生成的colormap导入进cmaps。并输出一个用于预览使用的icmap并在下面调用(23行 cmap=icmap)。

到此,我们自定义的colormap已经永久地存入cmaps模块中

这个仅用于颜色预览。在上面这个脚本中我们还不能使用cmaps,因为对cmaps程序进行了修改,一边修改一边使用它会出现错误和无效。预览完颜色,如果满意,今后就可以将23行改为:cmap=cmaps.testcolors  即可简单方便地永久调用自己制作的colormap了。如果不满意,可以继续调试,相同名字的colormap会更新覆盖,不用担心重名等问题。

获取完整代码,请关注我的公众号文章:colregister!永久导入自定义colormap!随时调用
小内存扫码_搜索联合传播样式-标准色版.png

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2022-5-12 15:36:53 | 显示全部楼层
你这个似乎不错,解决了一大痛点!我去试试,谢谢分享
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-8-15 21:41:13 | 显示全部楼层
楼主微信公众号密码还记得嘛,好久没更新了
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-8-16 08:25:34 | 显示全部楼层
不错的帖子,值得收藏。
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2022-9-7 11:45:18 | 显示全部楼层

不错的帖子,值得收藏。
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表