2
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

気象分野でPython&機械学習Advent Calendar 2023

Day 2

2023年の天気図をGIFアニメーションで振り返ってみる

Posted at

概要

2023年も残りわずかということで、今年の天気図をGIFアニメーションで動画化して振り返ってみました。

データの準備

気象庁のサイトでは毎日3時間ごと(日本時間0時除く)の日本周辺域の実況天気図を公開しています。

これらの天気図を使いたいところなのですが、画像のURLパスを見てみると…

https://www.jma.go.jp/bosai/weather_map/data/png/20231128020830_0_Z__C_010000_20231128000000_MET_CHT_JCIspas_JCP600x581_JRcolor_Tjmahp_image.png

となっていました。
最後のスラッシュの後に、日時の情報があるのでこれらを変えれば画像にアクセスできるはずです。

しかし、よくよく見てみるとURLの形式は以下のようになっています。

https://www.jma.go.jp/bosai/weather_map/data/png/  #ここは共通
20231128020830   # 画像をアップした日時(UTC:YYYYMMDDhhmmss)?
_0_Z__C_010000_  # ここも共通
20231128000000   # 天気図の日時(UTC:YYYYMMDDhhmmss)
_MET_CHT_JCIspas_JCP600x581_JRcolor_Tjmahp_image.png  # ここも共通

画像のアップロード日時らしきものがURLに入ってしまっているため、これだと難しいですね…1

そこで、100年天気図データベースという気象庁の天気図をアーカイブしているサイトを使います。

例えば2023年11月28日9時の天気図画像のURLは

http://agora.ex.nii.ac.jp/digital-typhoon/weather-chart/wxchart/202311/SPAS_COLOR_202311280000.png

となっており、/202311/202311280000の部分を書き換えれば他の日時の天気図へもアクセス可能です。

データ取得はPythonで行いました。コード例は以下です。
日本時間の2023年1月1日3時~11月27日21時までの天気図画像を/data/ディレクトリ内に保存します。

./data/collect-data.py
import os
import urllib.request
import urllib.error
import urllib.parse
import time
import datetime

#### 期間を指定 ####
# 開始日時(UTC)
start = datetime.datetime(2022, 12, 31, 18, 0, 0)
# 終了日時(UTC)
end = datetime.datetime(2023, 11, 27, 12, 0, 0)
####################


savedir = './'  # データ保存先ディレクトリ
if not os.path.exists(savedir):
    os.makedirs(savedir)

d = start
while d <= end:
    if d.hour in [0, 3, 6, 9, 12, 18, 21]:
        # データ取得先URL
        url = f'http://agora.ex.nii.ac.jp/digital-typhoon/weather-chart/wxchart/{d.year}{d.month:02d}/SPAS_COLOR_{d.strftime("%Y%m%d%H%M")}.png'

        # ファイル名
        basename = os.path.basename(url)
        savename = os.path.join(savedir, basename)

        # ファイルが存在しない場合のみダウンロード
        if not os.path.exists(savename):
            try:
                urllib.request.urlretrieve(url, savename)
                time.sleep(1)
                print('downloaded:', basename)
            except urllib.error.URLError as e:
                print(url)
                print(e)
        else:
            print('file exists:', basename)

    d += datetime.timedelta(hours=3)

GIFアニメーションの作成

Anthropicが開発したAIチャット「Claude」に、GIFの作り方を聞いたら一発で動きました。

Claudeの回答コードで.save()の引数を若干いじったものを、下に載せておきます。

generate-gif.py
from PIL import Image
import glob

frames = []
imgs = glob.glob("./data/*.png")
for i in imgs:
    new_frame = Image.open(i)
    frames.append(new_frame)

frames[0].save('animation.gif', format='GIF', append_images=frames[1:], save_all=True, duration=50, loop=0, optimize=True)

そして、出来上がったGIFアニメーションがこちらです。
※全部やると163MBとなり、Qiitaにアップロードできなかったので、下ではShort版を見せています。

animation-short.gif

save()の引数を簡単に説明しておくと、

  • save_allTrueにしておかないとアニメーションにならない
  • duration:1フレームあたりの表示時間(単位:ミリ秒)
  • loop0にすると無限ループ、1以上にするとその指定回数で再生停止
  • optimizeTrueにするとGIF画像の最適化2が行われる

ソースコード

今回使ったコードなどはGitHubに上げています。
本記事のは02-weathermapに入っています。

  1. 全探索すれば不可能ではないです。

  2. Claudeによると、GIFのフレーム間で共通しているピクセルは1回しか定義しない、ピクセルのパターンを辞書登録して圧縮する、などしているらしい(事実確認はしていない)。

2
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?