动画化海洋温度图 [英] Animating a map of ocean temperature

查看:73
本文介绍了动画化海洋温度图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有12个子图显示了凯尔特海的海洋温度变化.每个子图对应一年中的不同月份.

 将xarray导入为xa将cmocean.cm导入为cm导入matplotlib.patches作为mpatches从matplotlib.patches导入补丁从matplotlib.lines导入Line2D导入matplotlib.pyplot作为plt将matplotlib.animation导入为ani将seaborn导入为sns将熊猫作为pd导入导入plotly.express为px进口pycountry将cartopy.crs导入为ccrs将cartopy.feature导入为cfeat#============================================================================#步骤1:获取数据#============================================================================data_model = xa.open_dataset("PD_tavg_out_atlanticcentric.nc",decode_times = False)sal_obs_data = xa.open_dataset("sal_obs_CS_all.nc",decode_times = False)temp_obs_data = xa.open_dataset("temp_obs_CS_all.nc",decode_times = False)data_obs = xa.merge([sal_obs_data,temp_obs_data])data_obs = data_obs.rename(lon =经度",lat ="latitude")#============================================================================#步骤2:定义座标#============================================================================long_max = 122.4long_min = 100.8lat_max = 25.2lat_min = 0dep_max = 100dep_min = 0tim_max = 35406.0tim_min = 35405.0def extract_shelf_sea(long_max,long_min,lat_max,lat_min,dep_max,dep_min,tim_max,tim_min):#=============================================================================#步骤3:提取数据#============================================================================extract_model_data = data_model.sel(经度=切片(long_min,long_max),纬度=切片(lat_min,lat_max),深度=切片(dep_min,dep_max),时间=切片(tim_min,tim_max))extract_obs_data = data_obs.sel(time = data_obs.time,经度= data_obs.longitude,纬度= data_obs.latitude,depth = extract_model_data.depth,方法=最近")#=============================================================================#步骤4:计算盐度和温度之差#============================================================================model_diff = extract_model_data.diff("depth")obs_diff = extract_obs_data.diff("depth")返回model_diff,obs_diff#============================================================================#步骤5:绘制#============================================================================def plot_SCS():CS_model,CS_obs = extract_shelf_sea(2,-17,65,45,100,0,35405.95,35405)map_proj = ccrs.Orthographic(central_longitude = -8.5,central_latitude = 55)#============================================================================#观测数据(温度)#============================================================================temp_obs = CS_obs.tempmap_proj = ccrs.Orthographic(central_longitude = -8.5,central_latitude = 55)情节= temp_obs.plot(cmap = cm.curl,cbar_kwargs = {'label':'温度在15m和82m(°C)之间的变化'},col ='time',col_wrap = 4,变换= ccrs.PlateCarree(),subplot_kws = {投影":map_proj},vmin = -6,vmax = 6)plot.fig.suptitle(凯尔特海-观测数据")斧头,zip(plot.axes.flat,['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']):ax.set_title(标题)对于plot.axes.flat中的斧头:ax.add_feature(cfeat.LAND,zorder = 100,edgecolor ="k",facecolor ="gray") 

我想对此进行动画处理,所以我只有一个情节,但它每秒都会移动到下个月.我已经尝试过使用plotly和matplotlib动画做一些事情,但没有成功.

我什至不知道还能尝试什么.任何建议都有帮助!抱歉,我无法附加完整的原始数据集,因为它是一个巨大的文件.

解决方案

您的案例非常适合使用

I have 12 subplots showing changes in ocean temperature for the Celtic Sea. Each subplot is for a different month in the year.

import xarray as xa
import cmocean.cm as cm
import matplotlib.patches as mpatches
from matplotlib.patches import Patch
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import seaborn as sns
import pandas as pd
import plotly.express as px
import pycountry
import cartopy.crs as ccrs
import cartopy.feature as cfeat



# =============================================================================
#  Step 1: Get data
# =============================================================================
    
data_model = xa.open_dataset("PD_tavg_out_atlanticcentric.nc",decode_times = False)

sal_obs_data = xa.open_dataset("sal_obs_CS_all.nc",decode_times = False)
temp_obs_data = xa.open_dataset("temp_obs_CS_all.nc",decode_times = False)

data_obs = xa.merge([sal_obs_data,temp_obs_data])
data_obs = data_obs.rename(lon = "longitude",
                           lat = "latitude")

# =============================================================================
#  Step 2: Define Coordinates 
# =============================================================================
 
long_max = 122.4
long_min = 100.8
lat_max = 25.2
lat_min = 0
dep_max = 100
dep_min = 0
tim_max = 35406.0
tim_min = 35405.0 

def extract_shelf_sea(long_max, long_min, 
                      lat_max, lat_min,
                      dep_max, dep_min,
                      tim_max, tim_min):

# =============================================================================
#  Step 3: Extract data
# =============================================================================

    extract_model_data = data_model.sel(longitude = slice(long_min,long_max),
                                        latitude = slice(lat_min,lat_max),
                                        depth = slice(dep_min,dep_max),
                                        time = slice(tim_min,tim_max))
    
    
    extract_obs_data = data_obs.sel(time = data_obs.time,
                                    longitude = data_obs.longitude,
                                    latitude = data_obs.latitude,
                                    depth = extract_model_data.depth, method="nearest")
    
# =============================================================================
#  Step 4: Calculating the difference in salinity and temperature
# =============================================================================

    model_diff = extract_model_data.diff("depth")
    obs_diff = extract_obs_data.diff("depth")
    
    return model_diff, obs_diff


# =============================================================================
#  Step 5: Plotting
# =============================================================================

def plot_SCS():
    
    CS_model, CS_obs = extract_shelf_sea(2,-17,65,45,100,0,35405.95,35405)
    
    map_proj = ccrs.Orthographic(central_longitude = -8.5, central_latitude = 55)

        
# =============================================================================
#     Observational Data (temperature)
# =============================================================================

    temp_obs = CS_obs.temp
    map_proj = ccrs.Orthographic(central_longitude = -8.5, central_latitude = 55)
    plot = temp_obs.plot(cmap = cm.curl,
                         cbar_kwargs = {'label':'Change in temperature between 15m and 82m (°C)'},
                         col='time', col_wrap=4, 
                         transform = ccrs.PlateCarree(),
                         subplot_kws={"projection":map_proj},
                         vmin=-6, vmax=6)
    plot.fig.suptitle("Celtic Sea - Observational Data")

    for ax, title in zip(plot.axes.flat, ['Jan','Feb','Mar','Apr','May','Jun',
                                          'Jul','Aug','Sep','Oct','Nov','Dec']):
        ax.set_title(title)
    
    for ax in plot.axes.flat:
        ax.add_feature(cfeat.LAND,zorder=100,edgecolor="k",facecolor="gray")
    
    

I'd like to animate this, so I only have a single plot, but every second or so it moves to the next month. I've tried a few things with plotly and the matplotlib animation and haven't had any success.

I don't even really know what else to try. Any advice helpful! Sorry, I can't attach the full original dataset as it's a huge file.

解决方案

Your case is excellent for the use of ArtistAnimation, i.e., the flipbook approach using precomputed images. Sample code because the format of your animation is not specified:

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

fig, axes = plt.subplots(ncols=6, nrows=3, figsize=(15, 10))
#get specs for large image
gs = axes[0, -2].get_gridspec()

#remove unnecessary axis objects
for ax in axes[0:, -2:].flat: 
    ax.remove()
  
#update axes list and label all static images
axes = fig.get_axes()
for i, ax in enumerate(axes): 
    ax.axis("off")
    ax.set_title(f"month {i+1}")

#add axis object for large, animated image
ax_large = fig.add_subplot(gs[0:, -2:])
ax_large.axis("off")

#fake images
def f(x, y, i):
    return np.sin(x*i/4) * i/6 + np.cos(y* (12-i)/4) 

x = np.linspace(0, 2 * np.pi, 80)
y = np.linspace(0, 2 * np.pi, 120).reshape(-1, 1)

all_ims = []
min_v = -3
max_v = 3
ani_cmap = "seismic"

for i, ax_small in enumerate(axes):
    #image generation unnecessary for you because your images already exist
    arr = f(x, y, i)
    #static image into small frame
    im_small = ax_small.imshow(arr, vmin=min_v, vmax=max_v, cmap=ani_cmap)
    #animated image into large frame
    im_large = ax_large.imshow(arr, animated=True, vmin=min_v, vmax=max_v, cmap=ani_cmap)
    #animated images are collected in a list
    all_ims.append([im_large])

ani = animation.ArtistAnimation(fig, all_ims, interval=200, blit=True)

plt.show()

Sample output:

这篇关于动画化海洋温度图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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