【问题标题】:Dynamic Visualisation of Global Plots全局图的动态可视化
【发布时间】:2020-05-23 18:01:51
【问题描述】:

我制作了 17 个全球图表,显示了 1850 年至 2015 年最大地表臭氧的年代际平均值。我不想单独绘制它们,而是希望创建一个循环遍历它们的动画(几乎像一个 gif),即始终具有相同的海岸线、轴和颜色条,但将绘制的内容更改为轮廓。

任何有关如何调整我的代码以执行此操作的帮助将不胜感激 - 提前感谢您!

import numpy as np
import netCDF4 as n4
import matplotlib.pyplot as plt
from matplotlib import colorbar, colors
import matplotlib.cm as cm

import cartopy as cart
import cartopy.crs as ccrs
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import cartopy.feature as cfeature

nc = n4.Dataset('datafile.nc','r')

# daily maximum O3 VMR (units: mol mol-1)
sfo3max = nc.variables['sfo3max']
lon = nc.variables['lon'] # longitude
lat = nc.variables['lat'] # latitude

# (I manipulate the data to produce 17 arrays containing the decadal average O3 VMR which are
#  listed below in sfo3max_avg)

sfo3max_avg = [sfo3max_1850_1860_avg, sfo3max_1860_1870_avg, sfo3max_1870_1880_avg,
               sfo3max_1880_1890_avg, sfo3max_1890_1900_avg, sfo3max_1900_1910_avg,
               sfo3max_1910_1920_avg, sfo3max_1920_1930_avg, sfo3max_1930_1940_avg,
               sfo3max_1940_1950_avg, sfo3max_1950_1960_avg, sfo3max_1960_1970_avg,
               sfo3max_1970_1980_avg, sfo3max_1980_1990_avg, sfo3max_1990_2000_avg,
               sfo3max_2000_2010_avg, sfo3max_2010_2015_avg]

# find overall min & max values for colour bar in plots
min_sfo3max_avg = np.array([])
for i in sfo3max_avg:
    sfo3max_avg_min = np.amin(i)
    min_sfo3max_avg = np.append(min_sfo3max_avg, sfo3max_avg_min)
overall_min_sfo3max_avg = np.amin(min_sfo3max_avg)

max_sfo3max_avg = np.array([])
for i in sfo3max_avg:
    sfo3max_avg_max = np.amax(i)
    max_sfo3max_avg = np.append(max_sfo3max_avg, sfo3max_avg_max)
overall_max_sfo3max_avg = np.amax(max_sfo3max_avg)

# finally plot the 17 global plots of sfo3max_avg
for k in sfo3max_avg:
    fig = plt.figure()
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines() # Adding coastlines
    cs = ax.contourf(lon[:], lat[:], k[:], cmap='magma')
    ax.set_title('Decadal Average of Maximum O3 Volume Mixing Ratio')

    m = plt.cm.ScalarMappable(cmap=cm.magma)
    m.set_array(i[:])
    m.set_clim(overall_min_sfo3max_avg, overall_max_sfo3max_avg)

    # Additional necessary information
    cbar = plt.colorbar(m, boundaries=np.arange(overall_min_sfo3max_avg, overall_max_sfo3max_avg
                        + 0.5e-08, 0.5e-08))
    cbar.set_label('mol mol-1')

    # Adding axis labels - latitude & longitude
    gridl = ax.gridlines(color="black", linestyle="dotted", draw_labels=True) 
    gridl.xformatter=LONGITUDE_FORMATTER
    gridl.yformatter=LATITUDE_FORMATTER
    gridl.xlabels_top = False
    gridl.ylabels_right = False

    fig.set_size_inches(w=20,h=10)
    plt.show() # show global plot

【问题讨论】:

    标签: python matplotlib cartopy matplotlib-animation


    【解决方案1】:

    绘图中的几个元素可以被排除在循环之外,因为它们只需要设置一次。设置绘图元素后,您可以通过循环遍历列表来更新绘图和动画。这可以通过使用matplotlib的交互模式来实现,如下代码所示:

    import numpy as np
    import netCDF4 as n4
    import matplotlib
    matplotlib.use("nbagg")
    
    import matplotlib.pyplot as plt
    from matplotlib import colorbar, colors
    import matplotlib.cm as cm
    
    import cartopy as cart
    import cartopy.crs as ccrs
    from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
    import cartopy.feature as cfeature
    
    nc = n4.Dataset('datafile.nc','r')
    
    # daily maximum O3 VMR (units: mol mol-1)
    sfo3max = nc.variables['sfo3max']
    lon = nc.variables['lon'] # longitude
    lat = nc.variables['lat'] # latitude
    
    # (I manipulate the data to produce 17 arrays containing the decadal average O3 VMR which are
    #  listed below in sfo3max_avg)
    
    sfo3max_avg = [sfo3max_1850_1860_avg, sfo3max_1860_1870_avg, sfo3max_1870_1880_avg,
                   sfo3max_1880_1890_avg, sfo3max_1890_1900_avg, sfo3max_1900_1910_avg,
                   sfo3max_1910_1920_avg, sfo3max_1920_1930_avg, sfo3max_1930_1940_avg,
                   sfo3max_1940_1950_avg, sfo3max_1950_1960_avg, sfo3max_1960_1970_avg,
                   sfo3max_1970_1980_avg, sfo3max_1980_1990_avg, sfo3max_1990_2000_avg,
                   sfo3max_2000_2010_avg, sfo3max_2010_2015_avg]
    
    # find overall min & max values for colour bar in plots
    min_sfo3max_avg = np.array([])
    for i in sfo3max_avg:
        sfo3max_avg_min = np.amin(i)
        min_sfo3max_avg = np.append(min_sfo3max_avg, sfo3max_avg_min)
    overall_min_sfo3max_avg = np.amin(min_sfo3max_avg)
    
    max_sfo3max_avg = np.array([])
    for i in sfo3max_avg:
        sfo3max_avg_max = np.amax(i)
        max_sfo3max_avg = np.append(max_sfo3max_avg, sfo3max_avg_max)
    overall_max_sfo3max_avg = np.amax(max_sfo3max_avg)
    
    #setup the plot elements
    fig = plt.figure()
    fig.set_size_inches(w=20,h=10)
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines() # Adding coastlines
    ax.set_title('Decadal Average of Maximum O3 Volume Mixing Ratio')
    
    m = plt.cm.ScalarMappable(cmap=cm.magma)
    m.set_array(i[:])
    m.set_clim(overall_min_sfo3max_avg, overall_max_sfo3max_avg)
    
    
    # Additional necessary information
    cbar = plt.colorbar(m, boundaries=np.arange(overall_min_sfo3max_avg, overall_max_sfo3max_avg
                        + 0.5e-08, 0.5e-08))
    cbar.set_label('mol mol-1')
    
    # plot here only the 1st item in your sfo3max_avg list.
    cs = ax.contourf(lon[:], lat[:], sfo3max_avg[0][:], cmap='magma')
    
    # Adding axis labels - latitude & longitude
    gridl = ax.gridlines(color="black", linestyle="dotted", draw_labels=True) 
    gridl.xformatter=LONGITUDE_FORMATTER
    gridl.yformatter=LATITUDE_FORMATTER
    gridl.xlabels_top = False
    gridl.ylabels_right = False
    
    
    plt.ion()   # set interactive mode
    plt.show()
    
    # finally plot the 17 global plots of sfo3max_avg
    for k in sfo3max_avg:
        cs = ax.contourf(lon[:], lat[:], k[:], cmap='magma')
        plt.gcf().canvas.draw()
        plt.pause(1) #control the interval between successive displays, currently set to 1 sec.
    

    【讨论】:

    • 我已经在 J​​upyter 笔记本中编写了这段代码 - 我在 import matplotlib.pyplot as plt 之前添加了 %matplotlib inline,它成功绘制了第一个图,然后在图下方打印了 16 次 <Figure size 432x288 with 0 Axes>。我也试过%matplotlib notebook,它甚至没有绘制初始图,而是打印Javascript Error: Can’t find variable: IPython。运行第一个单元格时,仅使用 %matplotlib 会产生以下错误:ValueError: Namespace Gtk not available for version 3.0
    • 你需要在 Jupyter notebook 中使用交互式背景:import matplotlib 然后matplotlib.use("nbagg")
    • 交互式后端*
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多