Py学习  »  Python

Python脚本一键转换netCDF文件为GIF或者MP4动态文件

气象学家 • 3 年前 • 412 次点击  

netcdf2mp4:一个Python脚本用于从时空NetCDF数据集创建动画数据GIF和MP4格式的可视化。

脚本库地址:

https://github.com/johannesuhl/netcdf2mp4


此脚本用于读取 NetCDF 数据,用于绘制每个时间点的数据,并用于创建动画 GIF。最后,它用于将动画gif转换为MP4视频格式,这将减小文件大小。例如,下面的GIF是29MB,相应的MP4文件小于3MB。图片视频压缩推荐:https://ezgif.com/

依赖的主要库:gdal matplotlib imageio moviepy

例如,此脚本可用于可视化CRU TS月度高分辨率网格多变量气候数据集中每个0.5°x 0.5°网格单元从1901-2020年的平均月温度(Harris等人,2020;https://www.nature.com/articles/s41597-020-0453-3)。

CRU平均温度(1901-2020)

# -*- coding: utf-8 -*-
"""
Created on Wed Aug 25 16:22:57 2021

@author: Johannes H. Uhl, University of Colorado Boulder, USA.
"""


import os,sys
import numpy as np
import datetime
from matplotlib import pyplot as plt
from osgeo import gdal
import imageio
#import ffmpy
import moviepy.editor as mp
import matplotlib
matplotlib.rcParams['font.sans-serif'] = "Arial"
matplotlib.rcParams['font.family'] = "sans-serif"
plt.rcParams['figure.autolayout'] = True

# user parameters #########################################################################
netcdf_file = r'.\cru_ts4.05.1901.2020.tmp.dat.nc\cru_ts4.05.1901.2020.tmp.dat.nc' # input netcdf file
netcdf_var = 'tmp' #variable of interest
output_gif = r'.\cru_ts4.05.1901.2020.tmp.gif' #output gif file
output_mp4 = r'.\cru_ts4.05.1901.2020.tmp.mp4' #output mp4 file
frame_duration = 0.1 #seconds per frame
nodatavalue=9e+36 # will be set to background color
### color scheme
cmap = matplotlib.cm.get_cmap("turbo").copy()
cmap.set_bad('black'#background color
vmin=-30
vmax=30
##########################################################################################

### open netcdf file as array
infile='NETCDF:"'+netcdf_file+'":%s' %(netcdf_var)

ds=gdal.Open(infile)
arr=ds.ReadAsArray()

### get dates
timevalues=ds.GetMetadata()['NETCDF_DIM_time_VALUES'][1:-1].split(',')
timevalues=[int(x) for x in timevalues]
startdate = datetime.datetime.strptime("01/01/1900""%m/%d/%Y")
datetime_vals=[(startdate+datetime.timedelta(days=x)) for x in  timevalues]

### plot each frame to a temporary png image file
filenames = []
epochs=len(timevalues)
for t in np.arange(0,epochs):
    currarr=arr[t,:,:]    
    currarr[currarr>nodatavalue]=-np.nan  ### set no data value to nan
    currdate=datetime_vals[t]
    
    ### select a temporal subset
    #if not currdate.month in [2,4,6,8,10,12]:
    #    continue
    
    ### format the date for plotting and file names:
    currdate_fmt = '%s/%s/%s' %(currdate.year,str(currdate.month).zfill(2),str(currdate.day).zfill(2))
    currdate_fmt2 = '%s-%s' %(str(currdate.month).zfill(2),currdate.year)
    
    ### set up plot
    fig,ax=plt.subplots(figsize=(6,3.5)) ##adjust image aspect to your data
    img=ax.imshow(currarr,cmap=cmap,vmin=vmin,vmax=vmax) ##adjust vmin and vmax to your data
    ax.set_xticks([])
    ax.set_yticks([])
    
    ### add some text:
    ax.set_xlabel('Data source: CRU TS monthly high-resolution gridded multivariate climate dataset\n Visualization: Johannes H. Uhl, University of Colorado Boulder (USA), 2022.', fontsize=9)
    ax.set_title('Average monthly temperature [°C] from 1901 to 2020\n'+currdate_fmt2, fontsize=15)

    ### customize color bar:
    cbar = fig.colorbar(img,fraction=0.02)
    cbar.set_ticklabels(['{0:+}'.format(int(xx)) if xx!=0 else int(xx) for xx in cbar.ax.get_yticks()]) ## add sign to colorbar ticks
    #from : https://stackoverflow.com/questions/19219963/align-ticklabels-in-matplotlib-colorbar
    ticklabs = cbar.ax.get_yticklabels()
    cbar.ax.set_yticklabels(ticklabs,ha='right')
    cbar.ax.yaxis.set_tick_params(pad=20)

    ### set edges to white:
    ax.tick_params(axis='x', colors='white')
    ax.tick_params(axis='y', colors='white')
    #plt.show() ### uncomment for testing
    
    ### save frame to png
    filename = '%s.png' %currdate_fmt.replace('/','')
    fig.tight_layout(pad=0#possibly unnecessary as we set rcparams
    fig.savefig(filename,pad_inches = 0#pad_inches is possibly unnecessary as we set rcparams
    plt.close()
    filenames.append(filename) 
    print(currdate_fmt)
    
    ### uncomment to test a few frames:
    # if t>20:
    #     break
    
# build gif
with imageio.get_writer(output_gif, mode='I',duration=frame_duration) as writer:
    for filename in filenames:
        if os.path.exists(filename):
            image = imageio.imread(filename)
            writer.append_data(image)

# convert to mp4
clip = mp.VideoFileClip(output_gif)
clip.write_videofile(output_mp4)

# Remove temporary files
for filename in set(filenames):
    if os.path.exists(filename):
        os.remove(filename)

有关 CRU 数据提取和可视化的更多代码,请参阅:

 https://github.com/johannesuhl/cru_data_processing

引用:

Harris, I., Osborn, T. J., Jones, P., & Lister, D. (2020). Version 4 of the CRU TS monthly high-resolution gridded multivariate climate dataset. Scientific data, 7(1), 1-18. https://doi.org/10.1038/s41597-020-0453-3


声明:欢迎转载、转发本号原创内容,可留言区留言或者后台联系小编(微信:gavin7675)进行授权。气象学家公众号转载信息旨在传播交流,其内容由作者负责,不代表本号观点。文中部分图片来源于网络,如涉及作品内容、版权和其他问题,请后台联系小编处理。





往期推荐

 ERA5-Land陆面高分辨率再分析数据(~16TB)

★ ERA5常用变量再分析数据(~11TB)

 TRMM 3B42降水数据(Daily/3h)

 科研数据免费共享: GPM卫星降水数据

 气象圈子有人就有江湖,不要德不配位!

 请某气象公众号不要 “以小人之心,度君子之腹”!

 EC数据商店推出Python在线处理工具箱

★ EC打造实用气象Python工具Metview

★ 机器学习简介及在短临天气预警中的应用

★ AMS推荐|气象学家-海洋学家的Python教程

★ Nature-地球系统科学领域的深度学习及理解

★ 采用神经网络与深度学习来预报降水、温度


   欢迎加入气象学家交流群   

请备注:姓名/昵称-单位/学校-研究方向

未备注的不通过申请



❤️ 「气象学家」 点赞

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/137553