使用 xarray 进行重新采样和插值来动画轮廓的移动

问题描述 投票:0回答:1

假设我有以下Python代码,显示中午12点和下午1点的轮廓值,表明它的位置已经移动:

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation


%matplotlib widget

ani = None
# Create the data array for the first time point
data_12 = np.zeros((1, 6, 6))  # Creating a 3D array with time dimension (1), and size 6x6
data_12[0, 1, 1] = 6  # Setting the value at 1x1 location to 6

# Create the xarray dataset for the first time point
ds_12 = xr.Dataset(
    {
        "value": (["time", "x", "y"], data_12)
    },
    coords={
        "time": [np.datetime64("2024-01-01T12:00")],
        "x": np.arange(6),
        "y": np.arange(6),
    },
)

# Create the data array for the second time point
data_13 = np.zeros((1, 6, 6))
data_13[0, 0, 0] = 0
data_13[0, 4, 4] = 6
ds_13 = xr.Dataset(
    {
        "value": (["time", "x", "y"], data_13)
    },
    coords={
        "time": [np.datetime64("2024-01-01T13:00")],
        "x": np.arange(6),
        "y": np.arange(6),
    },
)

ds_concat = xr.concat([ds_12, ds_13], dim="time")
ds_interp = ds_concat.resample(time="1min").interpolate("linear")
fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)

data_selected = ds_interp.isel(time=1)
cont = ax.contourf(data_selected["x"], data_selected["y"],data_selected["value"], cmap='viridis')

def animatehere(i):
    global cont
    data_selected = ds_interp.isel(time=i)
    cont = ax.contourf(data_selected["x"], data_selected["y"],data_selected["value"], cmap='viridis')
    return cont

def init():
    pass

ani = FuncAnimation(fig,animatehere,init_func=init, frames=60,interval=30, repeat=False)
ani.save('animation.gif', writer='pillow')
plt.show()

这将创建以下输出。

我想知道如何插入这些数据,以便它显示轮廓从一个点移动到另一个点,而不是简单地消失在一个位置并重新出现在另一个位置。在此示例中,强度没有变化,一个位置为 6,另一个位置为 6,但任何解决方案都应该能够处理强度随时间变化的情况。

有人可以给我举个例子来说明它是如何工作的或者为我指明正确的方向吗?

python numpy matplotlib scipy python-xarray
1个回答
0
投票

我尝试创建一个平滑的过渡,显示第一个点的强度下降,而第二个点的强度增加。

我改用数值作为时间维度,这让我可以更好地控制数据如何从一个点转换到另一个点。在动画中,我在每一帧开始时清除了情节。因此,方形轮廓在网格上平滑移动。

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Function to create a square-shaped contour
def square_blob(x, y, x0, y0, intensity, size=1):
    return intensity * ((np.abs(x - x0) <= size / 2) & (np.abs(y - y0) <= size / 2))

# Grid
x = np.arange(0, 6, 1)
y = np.arange(0, 6, 1)
X, Y = np.meshgrid(x, y)


data_12 = square_blob(X, Y, 1, 1, 6, size=1)
data_13 = square_blob(X, Y, 4, 4, 6, size=1)

# Creating datasets
ds_12 = xr.DataArray(data_12, dims=['y', 'x'], coords={'x': x, 'y': y}).expand_dims(time=[np.datetime64("2024-01-01T12:00")])
ds_13 = xr.DataArray(data_13, dims=['y', 'x'], coords={'x': x, 'y': y}).expand_dims(time=[np.datetime64("2024-01-01T13:00")])

# Concatenate and interpolate
ds_concat = xr.concat([ds_12, ds_13], dim='time')

# Convert time to numeric values (seconds since epoch)
time_numeric = (ds_concat.time - np.datetime64('1970-01-01')) / np.timedelta64(1, 's')

# Interpolate using the numeric time values, then convert back to datetime
time_interp = np.linspace(time_numeric[0], time_numeric[-1], 60)
time_interp_datetime = np.datetime64('1970-01-01') + (time_interp * np.timedelta64(1, 's')).astype('timedelta64[ns]')
ds_interp = ds_concat.interp(time=time_interp_datetime)


fig, ax = plt.subplots()
ax.set_xlim(0, 5)
ax.set_ylim(0, 5)

def animate(i):
    ax.clear()
    ax.set_xlim(0, 5)
    ax.set_ylim(0, 5)
    data = ds_interp.isel(time=i)
    ax.contourf(data.x, data.y, data, levels=np.linspace(0, 6, 7), cmap='viridis')

ani = FuncAnimation(fig, animate, frames=len(ds_interp.time), interval=50)
ani.save('animation.gif', writer='pillow')
plt.show()

© www.soinside.com 2019 - 2024. All rights reserved.