Python | 泰勒图

news2024/9/24 13:18:02

写在前面

最近,开始对于CMIP6的一些数据进行评估。Talor图是一个很好展现模式间误差的方式,这里简单记录一下在python中的实现方式。

  • 主要为半图的画法

参考的代码为:

  • https://zenodo.org/records/5548061

效果大致下面这个样子

这边在原本代码基础上,主要是设置了三个坐标label的颜色以及内部网格线的颜色的区别。

其中,绿色弧线表示RMSE,黑色弧线表示STD,蓝色网格线表示相关系数correlation

修改

这里,原本的代码中std和correlation的网格线是相同的颜色,我这里强行为了将去区分开,相当于自己强行叠加了一层std的弧线,使其看起来是黑色,实际上他原本还是蓝色。

实现的代码是这样:

  • 里面的rlocs就是控制绘制std网格线的具体数值,可以根据自己的数据进行适当的修改
def add_grid(self,stdcolor,corrcolor, *args, **kwargs):
    grid = self._ax.grid(color=corrcolor,*args, **kwargs)
    """Add a grid."""
    rlocs = np.arange(0,90,10)  # 生成多个标准差值,可以根据需要进行更改
    for r in rlocs:
        print(r)
        circle = plt.Circle((0, 0), r, transform=self._ax.transData._b, color=stdcolor,
                            fill=False, linestyle='-',linewidth=1.5,zorder=2)
        self._ax.add_patch(circle)


    return grid

代码解释

  • 下面简答讲一下这个代码的主函数

    
def test1():
    """Display a Taylor diagram in a separate axis."""
    # Reference std
    stdref = 48.491

    # Samples std,rho,name
    samples = [[25.939, 0.3, "Model A"],
               [29.593, 0.5, "Model B"],
               [33.125, 0.6, "Model C"],
               [29.593, 0.7, "Model D"],
               [71.215, 0.473, "Model E"],
               [27.062, 0.360, "Model F"],
               [38.449, 0.342, "Model G"],
               [35.807, 0.609, "Model H"],
               [17.831, 0.360, "Model I"]]

    
    refstd = stdref
    
    fig = plt.figure(figsize=(12, 6),dpi=200)
    # Taylor diagram
    dia = TaylorDiagram(refstd, fig=fig, rect=111, label="Obs",
                        srange=(0., 1.8))
    
    colors = cmaps.matlab_jet(np.linspace(0, 1, len(samples)))
    

    # Add the models to Taylor diagram
    for i, model in enumerate(samples):
        print(i,model)

        marker_color = colors[i]
        label_color = 'black'           # Set legend label color to black
        dia.add_sample(samples[i][0], samples[i][1],
                        marker='$%d$' % (i+1),
                        ms=8, ls='',
                        mfc=marker_color, mec=marker_color,
                        label=f"{samples[i][2]}", color=label_color)  # Specify label color here
    # # Add grid
    dia.add_grid(stdcolor='k',corrcolor='blue',linestyle='-.')
    # # Add RMS contours, and label them
    contours = dia.add_contours(linestyle='--',color='green')
    plt.clabel(contours, inline=1, fontsize=10, fmt='%.2f')
    # # Add a figure legend
    legend = fig.legend(dia.samplePoints,
                    [p.get_label() for p in dia.samplePoints],
                    numpoints=1, prop={'size': 'small'}, ncol=2,
                    loc='upper right', frameon=False, bbox_to_anchor=(0.9, 0.7))
    plt.setp(legend.texts, color='black')
    plt.show()
    
    # save_figure(fig,'taylor diagram of cmip6 model')

    return dia

dia = test1()

  • stdref = 48.491

这个主要是一个参考的数值,可以将其是为观测真值的标准差的数值

samples = [[25.939, 0.3, "Model A"],
               [29.593, 0.5, "Model B"],
               [33.125, 0.6, "Model C"],
               [29.593, 0.7, "Model D"],
               [71.215, 0.473, "Model E"],
               [27.062, 0.360, "Model F"],
               [38.449, 0.342, "Model G"],
               [35.807, 0.609, "Model H"],
               [17.831, 0.360, "Model I"]]

要绘制这样的泰勒图呢,需要提供一个列表或者数组或者字典,如示例中的;

第一列是std,第二列是correlation,第三列是model的名称;放在代码里面如下所示,这几个数据是绘制泰勒图必要的参数。

其中,rmse不需要传递,他会自己根据你提供的std数据进行计算。

泰勒图可以其理解为由std和correlation的极坐标系,类似于我们普通绘制x-y的散度图。

知道了需要传递的数据类型,下面绘制数据的部分就容易很多了

 for i, model in enumerate(samples):
        print(i,model)

        marker_color = colors[i]
        label_color = 'black'           # Set legend label color to black
        dia.add_sample(samples[i][0], samples[i][1],
                        marker='$%d$' % (i+1),
                        ms=8, ls='',
                        mfc=marker_color, mec=marker_color,
                        label=f"{samples[i][2]}", color=label_color)  # Specify label color here
    # # Add grid
    dia.add_grid(stdcolor='k',corrcolor='blue',linestyle='-.')
    # # Add RMS contours, and label them
    contours = dia.add_contours(linestyle='--',color='green')
    plt.clabel(contours, inline=1, fontsize=10, fmt='%.2f')
    # # Add a figure legend
    legend = fig.legend(dia.samplePoints,
                    [p.get_label() for p in dia.samplePoints],
                    numpoints=1, prop={'size': 'small'}, ncol=2,
                    loc='upper right', frameon=False, bbox_to_anchor=(0.9, 0.7))

对于你提供的数据,循环传递,类似于绘制散度的形式,通过定义的dia类通过add_sample()函数进行传入,

  • add_sample(self, stddev, corrcoef, *args, **kwargs)

第一个为标准偏差std;第二个参数为相关系数corr;marker为显示的legend的编号类型,可以是数字,五角星,三角形,可以自由修改;
label是定义的model的名称,可以是model-1,model-2,或者说具体各个model的名称

  • dia.add_grid(stdcolor='k',corrcolor='blue',linestyle='-.')

添加泰勒图的网格线,这里提供两个参数,可以自定义修改std和corr的颜色

  • contours = dia.add_contours()

添加rmse的弧线,可以自定义线的类型,颜色等

  • legend = fig.legend(dia.samplePoints, [p.get_label() for p in dia.samplePoints], numpoints=1, prop={'size': 'small'}, ncol=2, loc='upper right', frameon=False, bbox_to_anchor=(0.9, 0.7))

设置了legend的摆放位置,可以自定义通过bbox_to_anchor进行微调

全部代码

  • 理论上,只需要替换sample的数据为自己的数据,就可以得到相应的绘制结果
# -*- coding: utf-8 -*-
"""
Created on %(date)s

@author: jianpu

@email : xianpuji@hhu.edu.cn


"""


import matplotlib.ticker as ticker
import xarray as xr
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import colors
import pandas as pd
from matplotlib import gridspec
from matplotlib.colors import ListedColormap 
import matplotlib.cm as cm
import matplotlib.colors as mcolors
import os
import glob
from datetime import datetime, timedelta
import cmaps
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import cftime
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.patches as patches


plt.rcParams['font.family'] = 'Times New Roman'   
plt.rcParams['font.size'] = 14

def save_figure(fig,filename='meridional_mean'):
    
    fnFIG = os.path.splitext(os.path.basename(__file__))[0]
    
    outfolder = fnFIG

    if not os.path.exists(outfolder):
        os.makedirs(outfolder)
        print(f'{outfolder} has been created')
    else:
        print(f'{outfolder} already exists')
    
    outpath = os.path.join(outfolder, filename)
    fig.savefig(outpath, dpi=300, bbox_inches='tight')



class TaylorDiagram(object):
    """
    Taylor diagram.

    Plot model standard deviation and correlation to reference (data)
    sample in a single-quadrant polar plot, with r=stddev and
    theta=arccos(correlation).
    """

    def __init__(self, refstd,
                  fig=None, rect=111, label='_', srange=(0, 1.5), extend=False,
                  xlabel='Obs'):
        """
        Set up Taylor diagram axes, i.e. single quadrant polar
        plot, using `mpl_toolkits.axisartist.floating_axes`.

        Parameters:

        * refstd: reference standard deviation to be compared to
        * fig: input Figure or None
        * rect: subplot definition
        * label: reference label
        * srange: stddev axis extension, in units of *refstd*
        * extend: extend diagram to negative correlations
        """

        from matplotlib.projections import PolarAxes
        import mpl_toolkits.axisartist.floating_axes as FA
        import mpl_toolkits.axisartist.grid_finder as GF

        self.refstd = refstd            # Reference standard deviation

        tr = PolarAxes.PolarTransform()

        # Correlation labels
        rlocs = np.array([0, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1])
        if extend:
            # Diagram extended to negative correlations
            self.tmax = np.pi
            rlocs = np.concatenate((-rlocs[:0:-1], rlocs))
        else:
            # Diagram limited to positive correlations
            self.tmax = np.pi/2
        tlocs = np.arccos(rlocs)        # Conversion to polar angles
        gl1 = GF.FixedLocator(tlocs)    # Positions
        tf1 = GF.DictFormatter(dict(zip(tlocs, map(str, rlocs))))

        # Standard deviation axis extent (in units of reference stddev)
        self.smin = srange[0] * self.refstd
        self.smax = srange[1] * self.refstd

        ghelper = FA.GridHelperCurveLinear(
            tr,
            extremes=(0, self.tmax, self.smin, self.smax),
            grid_locator1=gl1, tick_formatter1=tf1)

        if fig is None:
            fig = plt.figure()

        ax = FA.FloatingSubplot(fig, rect, grid_helper=ghelper)
        fig.add_subplot(ax)
        
        
        # Adjust axes
        ax.axis["right"].major_ticklabels.set_fontsize(18)
        ax.axis["left"].major_ticklabels.set_fontsize(18)
        ax.axis["top"].major_ticklabels.set_fontsize(18)
        ax.axis["top"].set_axis_direction("bottom")   # "Angle axis"
        ax.axis["top"].toggle(ticklabels=True, label=True)
        ax.axis["right"].toggle(ticklabels=True, label=True)
        ax.axis["top"].major_ticklabels.set_axis_direction("top")
        ax.axis["top"].label.set_axis_direction("top")
        ax.axis["left"].set_axis_direction("bottom")  # "X axis"
        
        ax.axis["right"].label.set_fontsize(22)
        ax.axis["right"].label.set_weight('bold')
        ax.axis["left"].label.set_fontsize(22)
        ax.axis["left"].label.set_weight('bold')
        ax.axis["top"].label.set_fontsize(22)
        ax.axis["top"].label.set_weight('bold')
        ax.axis["left"].label.set_color('red') 
        ax.axis["right"].label.set_color('k') 
        ax.axis["top"].label.set_color('b') 
        
        ax.axis["left"].label.set_text("Observation")
        ax.axis["right"].label.set_text("Standard deviation")
        ax.axis["top"].label.set_text("Correlation")
        
        ax.axis["left"].line.set_linewidth(2)
        ax.axis["top"].line.set_linewidth(2)
        ax.axis["right"].line.set_linewidth(2)
        
        ax.axis["right"].set_axis_direction("top")    # "Y-axis"
        ax.axis["right"].toggle(ticklabels=True)
        ax.axis["right"].major_ticklabels.set_axis_direction(
            "bottom" if extend else "left")

        if self.smin:
            ax.axis["bottom"].toggle(ticklabels=False, label=False)
        else:
            ax.axis["bottom"].set_visible(False)          # Unused

        self._ax = ax                   # Graphical axes
        self.ax = ax.get_aux_axes(tr)   # Polar coordinates

        # Add reference point and stddev contour
        l, = self.ax.plot([0], self.refstd, 'r*',
                          ls='', ms=10, label=label)
        t = np.linspace(0, self.tmax)
        r = np.zeros_like(t) + self.refstd
        self.ax.plot(t, r, 'r--', label='_')

        # Collect sample points for latter use (e.g. legend)
        self.samplePoints = [l]
        
    def draw_outer_border(self, ax):
        """
        Draw an outer border around the polar plot.
        """
        # Create a circle patch
        outer_border = patches.Circle(
            (0, 0), self.smax,
            transform=ax.transData._b,  # Use the polar transformation
            color='black', linewidth=2, fill=False, linestyle='--'
        )
        
        # Add the patch to the plot
        ax.add_patch(outer_border)
        
    def add_sample(self, stddev, corrcoef, *args, **kwargs):
        """
        Add sample (*stddev*, *corrcoeff*) to the Taylor
        diagram. *args* and *kwargs* are directly propagated to the
        `Figure.plot` command.
        """

        l, = self.ax.plot(np.arccos(corrcoef), stddev,
                          *args, **kwargs)  # (theta, radius)
        self.samplePoints.append(l)
        
        return l

    def add_grid(self,stdcolor,corrcolor, *args, **kwargs):
        grid = self._ax.grid(color=corrcolor,*args, **kwargs)
        """Add a grid."""
        rlocs = np.arange(0,90,10)  # 生成多个标准差值,可以根据需要进行更改
        for r in rlocs:
            print(r)
            circle = plt.Circle((0, 0), r, transform=self._ax.transData._b, color=stdcolor,
                                fill=False, linestyle='-',linewidth=1.5,zorder=2)
            self._ax.add_patch(circle)
        
        
        return grid

    def add_contours(self, levels=5, **kwargs):
        """
        Add constant centered RMS difference contours, defined by *levels*.
        """

        rs, ts = np.meshgrid(np.linspace(self.smin, self.smax),
                              np.linspace(0, self.tmax))
        # Compute centered RMS difference
        rms = np.sqrt(self.refstd**2 + rs**2 - 2*self.refstd*rs*np.cos(ts))

        contours = self.ax.contour(ts, rs, rms, levels,colors='green', linestyles='--', **kwargs)

        return contours




    
    
def test1():
    """Display a Taylor diagram in a separate axis."""
    # Reference std
    stdref = 48.491

    # Samples std,rho,name
    samples = [[25.939, 0.3, "Model A"],
               [29.593, 0.5, "Model B"],
               [33.125, 0.6, "Model C"],
               [29.593, 0.7, "Model D"],
               [71.215, 0.473, "Model E"],
               [27.062, 0.360, "Model F"],
               [38.449, 0.342, "Model G"],
               [35.807, 0.609, "Model H"],
               [17.831, 0.360, "Model I"]]

    
    refstd = stdref
    
    fig = plt.figure(figsize=(12, 6),dpi=200)
    # Taylor diagram
    dia = TaylorDiagram(refstd, fig=fig, rect=111, label="Obs",
                        srange=(0., 1.8))
    
    colors = cmaps.matlab_jet(np.linspace(0, 1, len(samples)))
    

    # Add the models to Taylor diagram
    for i, model in enumerate(samples):
        print(i,model)

        marker_color = colors[i]
        label_color = 'black'           # Set legend label color to black
        dia.add_sample(samples[i][0], samples[i][1],
                        marker='*',
                        ms=8, ls='',
                        mec=marker_color,
                        label=f"{samples[i][2]}", color=label_color)  # Specify label color here
    # # Add grid
    dia.add_grid(stdcolor='k',corrcolor='blue',linestyle='-.')
    # # Add RMS contours, and label them
    contours = dia.add_contours()
    plt.clabel(contours, inline=1, fontsize=10, fmt='%.2f')
    # # Add a figure legend
    legend = fig.legend(dia.samplePoints,
                    [p.get_label() for p in dia.samplePoints],
                    numpoints=1, prop={'size': 'small'}, ncol=2,
                    loc='upper right', frameon=False, bbox_to_anchor=(0.9, 0.7))
    plt.setp(legend.texts, color='black')
    plt.show()
    
    save_figure(fig,'taylor diagram of cmip6 model')

    return dia

dia = test1()


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2105204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

maven中如何配置多个仓库使其同时生效

场景 有一个项目&#xff0c;我把代码跟本地maven依赖包从同事那里拷贝过来&#xff0c;然后打包却一直打不了&#xff0c;一直报aliyun仓库找不到这个依赖的错误&#xff0c;无论我改成引用本地仓库还是线上aliyun仓库都不行。 依赖 <dependency><groupId>org.spr…

有三层交换机就不用路由器了?真的假的

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 晚上好&#xff0c;我的网工朋友。 在现代企业网络环境中&#xff0c;三层交换机因其高效的数据包处理能力和较低的延迟而受到广泛欢迎。 然而&…

Python 从入门到实战7(元组)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 之前的文章我们通过举例学习了python 中列表的定义及相关操作。今…

Echarts大屏可视化

构建可视化大屏&#xff1a; 构建布局&#xff1a;通过css和html对整个页面进行模块拆分&#xff0c;控制好每一张图的位置和大小&#xff0c;再将echarts实例化对象放到不同的盒子里 效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en&quo…

斯普林格-《土木工程与结构抗震设计》 Springer-Civil Engineering and Structural Seismic Design

文章目录 一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询 一、会议详情 二、重要信息 大会官网&#xff1a;https://ais.cn/u/vEbMBz提交检索&#xff1a;EI Compendex、IEEE Xplore、Scopus最终截稿&#xff1a;2024年9月2日23:59 三、大会介绍 四…

关于vue中v-model绑定radio表单元素的说明

在学习中&#xff0c;老师讲在v-model中&#xff0c;绑定的是radio的checked属性&#xff0c;起初看了例子后很不理解&#xff0c;于是开始寻找答案 老师所说的绑定关系 老师给的绑定代码&#xff0c;怎么看来&#xff0c;都不是实例的gender变量绑定radio的checked属性&…

2024 MongoDB 中国用户大会上海站成功举办圆满结束: 技术驱动未来,携手共创辉煌

一年一度 2024 MongoDB 中国用户大会上海站顺利举办&#xff0c;感谢大家的积极参与&#xff01; 在数字化浪潮的背景下&#xff0c;随着人工智能、物联网、5G等前沿技术的快速发展&#xff0c;如何利用这些技术实现业务创新&#xff0c;已成为中国企业在激烈市场竞争中保持领…

Vivado+PetaLinux 系统搭建教程

PetaLinux 是基于 Yocto project DDR SDRAM 双倍数据率同步动态随机存取存储器&#xff08;英语&#xff1a;Double Data Rate Synchronous Dynamic Random Access Memory&#xff0c;简称DDR SDRAM&#xff09;为具有双倍资料传输率的SDRAM&#xff0c;其资料传输速度为系统主…

Matplotlib | 绘制饼图

目录 简介安装 Matplotlib开始绘制简单饼图添加标签添加百分比修改显示方式突出扇形设置标题修改颜色实践&#xff1a;绘制七大洲面积比例图 简介 饼图&#xff08;Pie Chart&#xff09;&#xff0c;用扇形的面积&#xff0c;也就是圆心角的度数来表示数量。 饼图能够十分直…

【Java】ApiPost请求返回 `406` 状态码(jackson)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述3.1 问题截图3.2 错误简介3.2.1 HTTP状态码 406 Not Acceptable3.2.2 序列化和反序列化 3.3 后端问题位置…

yaml文件查看模型的架构

最近在看hrnet模型代码&#xff0c;想查看hrnet的模型架构&#xff0c;输出一下&#xff0c;但是模型参数需要cfg&#xff0c;我就想着怎么把yaml文件导进来然后打印模型呢&#xff0c;直接chat就可以了&#xff0c;下面解释一下每一部分&#xff0c;非常的好理解 yaml文件格式…

传神论文中心|第24期人工智能领域论文推荐

在人工智能领域的快速发展中&#xff0c;我们不断看到令人振奋的技术进步和创新。近期&#xff0c;开放传神&#xff08;OpenCSG&#xff09;传神社区发现了一些值得关注的成就。传神社区本周也为对AI和大模型感兴趣的读者们提供了一些值得一读的研究工作的简要概述以及它们各自…

ChatGPT 3.5/4.0使用手册:解锁人工智能的无限潜能

1. 引言 在人工智能的浪潮中&#xff0c;ChatGPT以其卓越的语言理解和生成能力&#xff0c;成为了一个革命性的工具。它不仅仅是一个聊天机器人&#xff0c;更是一个能够协助我们日常工作、学习和创造的智能伙伴。随着ChatGPT 3.5和4.0版本的推出&#xff0c;其功能和应用范围…

3个免费好用的网站,可以转换PDF,提取MP3

今天分享的三个网站&#xff0c;分别用于文件转换PDF&#xff0c;QMC转MP3格式和配色网站。 TOPDF 这个网站是一个在线PDF转换工具&#xff0c;可以快速将文本文件、演示文稿、电子表格和图片转换为PDF格式。它支持多种文件格式&#xff0c;如AZW3、BMP、CHM、CSV、DjVu、DOC、…

秋招突击——算法练习——8/30、9/4——技巧题练习——复习{}——新作{只出现一次的数字、多数元素、颜色分类、下一个排列、寻找重复数}

文章目录 引言复习新作136、只出现一次的数字个人实现 169、多数元素个人实现 75、颜色分类个人实现参考实现 31、下一个排列个人实现参考实现 287寻找重复数个人实现参考实现 总结 引言 手撕的代码大部分都是出自于这里&#xff0c;还是要继续加强&#xff0c;把剩下一些零碎…

10分钟学会Jmeter的用法

一提到接口测试&#xff0c;通常大家会有这样的疑问&#xff1a;前端测试不是已经覆盖到各种业务逻辑了吗&#xff1f;为什么还要做接口测试&#xff0c;接口测试和前端测试是不是重复了&#xff1f;对于这个问题&#xff0c;可以从下面几个方面来解释&#xff1a; 什么是接口…

Ubuntu共享文件夹的设置

ubuntu的操作路径时&#xff1a;/mnt/hgfs/51C_share

Mongodb 4.2.25 安装教程

一、上传部署包 1.1上传mongodb包进入/usr/local目录&#xff0c;将mongodb-linux-x86_64-rhel70-4.2.25.tgz包传到该目录下。 cd /usr/local 二、安装 2.1解压 tar zxvf mongodb-linux-x86_64-rhel70-4.2.25.tgz 2.2修改名称 mv mongodb-linux-x86_64-rhel70-4.2.25/ mong…

《OpenCV计算机视觉》—— 模板匹配

文章目录 一、模板匹配简单介绍二、三个主要函数的介绍1.执行模板匹配函数-cv2.matchTemplate()2.查找最佳匹配函数-cv2.minMaxLoc()3.在原图上绘制匹配区域函数-cv2.rectangle() 三、代码实现 一、模板匹配简单介绍 在Python中&#xff0c;模板匹配是一种在图像中查找与给定模…

记录一下blender烘焙贴图黑边的一个坑

首先是拆UV这里 margin 0.1 better share better 这个也大一点好了 这样烘焙的猴头就是正常的 这里的坑点是 降噪&#xff01;&#xff01;烘焙如果开启降噪 如果关闭下面那一个 会好一点&#xff0c;都关闭了&#xff0c;才是最上面的效果