Colaboratoryを使ってブラウザ上だけで気象レーダー画像を作成する

# はじめに
この資料ではプログラミング(ほぼ)0で以下のようなgif動画をブラウザ上で作成します。
![Radar_20200823.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658262/266d0a91-3a4f-d27e-6649-0bae208c5b1a.gif)

# 必要なもの
・Googleアカウント
(+余裕をもって1GBは空き容量のあるGoogleDrive)
・GoogleColaboratoryのほんの僅かな知識
(必要分は<a href="https://qiita.com/kogetaenoki/private/1bcd0d5535edb6f0d895">こちらの記事</a>で紹介しています。)


# 手順と詳細説明
# 実行方法について
スクリプトは2つに分かれています。最初に「セットアップ用」を実行し、その後その下に新しく「実行用」を入力して実行する流れです。

# スクリプト
以下はそれぞれコピペ+ユーザー設定（後述）の編集でOKです。

## セットアップ用
セットアップ時にはドライブのマウントの許可やランタイムのリセット等が求められる場合があります。そのまま指示に従ってポチポチしてください。

```python
from google.colab import drive
#********************************
# ドライブのマウント
# * * * * * * * * * * * * * * * *
drive.mount('/content/drive')
!pip3 install https://github.com/matplotlib/basemap/archive/master.zip
!pip3 install netCDF4
```
* 2022年3月16日修正
basemapを上記のリンクから取得するとエラーが生じるようになりました。
対処として、以下のリンクに差し替えれば問題なく動作することを確認しています。
https://github.com/matplotlib/basemap#subdirectory=packages/basemap
```python
!pip3 install git+https://github.com/matplotlib/basemap#subdirectory=packages/basemap
```


## 実行用
エラー発生時の対応方法については本記事末尾で説明します。

```python
#=======================================
# ALLDO
#=======================================
from google.colab import drive
import os, time
import datetime
import urllib.request
import tarfile
import pathlib
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from mpl_toolkits.basemap import Basemap
from PIL import Image
from email.mime.text import MIMEText
from email.header import Header
import smtplib, ssl

####################################
### ユーザーセッティング（ここから）
### # # # # # # # # # # # # # # # # 

#********************************
# ユーザー名の登録
# * * * * * * * * * * * * * * * *
user_name = "psycopath" #英数字のみ

#********************************
# 取得対象日の設定
# * * * * * * * * * * * * * * * *
# 8桁で入力する（yyyymodd）
# (例)　date_list = ["20200601" , "20200827"]
date_list = ["20180827"]

#取得対象日を日本標準時として扱う場合はflg_jst = 1
flg_jst = 1

#********************************
# 取得対象領域の設定
# * * * * * * * * * * * * * * * *
#気象レーダーの領域は以下の通り
# 経度(lon): 118.0 ～ 150.0
# 緯度(lat):  20.0 ～  48.0
#小数点も必ず含める（少なくとも少数第1位までは入力）
user_lon_min = 138.0
user_lon_max = 141.0
user_lat_min = 34.0
user_lat_max = 37.0

#********************************
# 出力先の設定
# * * * * * * * * * * * * * * * *
#(MyDrive配下の名前をodirとして登録する)
#(MyDrive/data/JMA/RADAR/配下に出力したい場合は、odir = 'data/JMA/RADAR')
o_dir = 'data/JMA/RADAR/Tokyo'

#さらにodirの下に日付毎のフォルダを作成するなら flg_datefold = 1, 不要なら0
flg_datefold = 1 #1を推奨

#********************************
# 地図の設定
# * * * * * * * * * * * * * * * *
# flg_border = 0: 県境なし、1: 県境あり、2: 市区町村境界あり
flg_border = 1
# 経線間隔（度）
lon_dx = 0.5
# 緯線間隔（度）
lat_dy = 0.5

#********************************
# 降水強度のカラースケール
# * * * * * * * * * * * * * * * *
# 左端以下は白、以降左から順に青～(虹の配色)～赤
levels = [0, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30] #mm/hr

#********************************
# gifの設定
# * * * * * * * * * * * * * * * *
# 1枚当たりの表示時間(ミリ秒)
dur_time = 200

#********************************
# 低フォルダ容量化の設定
# * * * * * * * * * * * * * * * *
# 元データが全国1kmメッシュデータで10分（1タイムステップ）毎に約33.1MB必要とする。
# (1日ともなれば合計で焼く4.77GBにも及ぶ。)
# (flg_foldsize = 1にすることを強く推奨する。)
flg_foldsize = 1 #1: 低容量化 #1以外: 再利用(効率化)

#********************************
#メール通知の設定（flg_datefold = 1のときのみ対応）
# * * * * * * * * * * * * * * * *
use_mail = 0 #1:使用, 0:不使用
## use_mail = 1 の場合（ここから）
mail_to = "aaaa.bbbb.cccc@xxx.yyy.zz" #送信先
send_name = "Radar_get info"          #差出人名
## 送信用アドレスの設定（以下のアドレスはテキトウなものです。ご自身で設定してください。）
gmail_account = "abcde@gmail.com"  #送信元アドレス
gmail_password = "abc123"          #送信元PW
#上のアカウントはメール通知用の捨アカです。
#（セキュリティ設定を下げないと自動送信機能が使えないため）
#もし個別に設定する場合はセキュリティの問題を承知した上で、日常利用のアカウントは使用しないようにしましょう。

#********************************
# wgrib2の設定
# * * * * * * * * * * * * * * * *
#  使用したいバージョンを登録する。
#  （ここから選ぶ https://www.ftp.cpc.ncep.noaa.gov/wd51we/wgrib2/ )
wgrb_ver = "wgrib2.tgz.v3.0.2"

### # # # # # # # # # # # # # # # # 
### ユーザーセッティング（ここまで）
####################################

#==========================================================================

#################################
### 以下は基本的に編集不要
#################################

#********************************
# ドライブの設定・作業ディレクトリの用意
# * * * * * * * * * * * * * * * *
drive_home = "/content/drive/MyDrive"

#出力先ディレクトリの指定
d_dir = f"{drive_home}/{o_dir}"
if not os.path.exists(d_dir): os.makedirs(d_dir)
work_dir = f"{d_dir}/{user_name}_work"
if not os.path.exists(work_dir): os.makedirs(work_dir)

#********************************
# wgrib2のセッティング
# (必要か自動で判断する)
# * * * * * * * * * * * * * * * *

# wgrib2の保存先の設定
wgrb2_dir = f"{drive_home}/lib_add/wgrib2"
if not os.path.exists(wgrb2_dir): os.makedirs(wgrb2_dir)
%cd $wgrb2_dir
wgrb_file = f"{wgrb2_dir}/{wgrb_ver}"

# URL（固定部）の設定
url_root = "https://www.ftp.cpc.ncep.noaa.gov/wd51we/wgrib2/"

# 指定バージョンのwgrib2の有無を判断＆ダウンロード
if not os.path.exists(wgrb_file):
  url = f"{url_root}{wgrb_ver}"
  !wget $url
else:
  print ("wgrib2 download: PATH")

# 指定バージョンのwgrib2ファイルの解凍の有無を判断＆解凍
grb2 = f"{wgrb2_dir}/grib2"
if not os.path.exists(grb2):
  !tar -zxvf $wgrb_ver
else:
  print ("wgrib2 unzip: PATH")

# 指定バージョンのwgrib2ファイルのコンパイルの有無を判断＆コンパイル
%cd $grb2
wgrb2 = f"{grb2}/wgrib2/wgrib2"
if not os.path.exists(wgrb2):
  %set_env CC gcc
  %set_env FC gfortran
  !make
else:
  print ("wgrib2 compile: PATH!")

# wgrib2コマンドの実行権限の設定
# (再ログイン時等に実行権限を失っている場合があるため)
%ls -l $wgrb2
!chmod a+x $wgrb2
%ls -l $wgrb2

# wgrib2コマンドの登録(%wgrib2 で呼び出せるようにする)
%alias wgrib2 $wgrb2
print ("wgrib2 is available!")
time.sleep(3)
%cd /content/

#********************************
# 日本領域の行政区境界情報の取得
# (必要か自動で判断する)
# 取得先は以下のURL(日本以外も選択可)
# https://gadm.org/download_country_v3.html
# * * * * * * * * * * * * * * * *

# 行政区情報の保存先の設定
border_dir = f"{drive_home}/lib_add/border"
if not os.path.exists(border_dir): os.makedirs(border_dir)
%cd $border_dir
# 行政区情報の取得
border_z_file = f"{border_dir}/gadm36_JPN_shp.zip"
if not os.path.exists(border_z_file):
  !wget https://biogeo.ucdavis.edu/data/gadm3.6/shp/gadm36_JPN_shp.zip
else:
  print ("gadm36_JPN_shp.zip download: PATH")
# 行政区情報の解凍
flg_border_z = f"{border_dir}/license.txt"
if not os.path.exists(flg_border_z):
  !unzip gadm36_JPN_shp.zip
else:
  print ("gadm36_JPN_shp.zip unzip: PATH")
# 行政区shapeファイルの選択
if flg_border == 0:
  border_shape = f"{border_dir}/gadm36_JPN_0"
elif flg_border == 1:
  border_shape = f"{border_dir}/gadm36_JPN_1"
elif flg_border == 2:
  border_shape = f"{border_dir}/gadm36_JPN_2"
else:
  print ("flg_border has illegal value!")
  exit
%cd /content/

#********************************
# 読み込み・切り取り用fortranソースコード
# * * * * * * * * * * * * * * * *

# このスクリプトが冗長になってしまうが、
#  all-in-oneの目的のためにここで.f90を作成
f90 = '''
  implicit none

!=======================================
! Original file's format
!- - - - - - - - - - - - - - - - - - - -
  integer,parameter :: ii   = 2560
  integer,parameter :: jj   = 3360
  real,   parameter :: lon0 = 118.0d0
  real,   parameter :: dlon = 0.0125000d0
  real,   parameter :: lat0 = 20.0d0
  real,   parameter :: dlat = 0.5d0/60.d0
!=======================================

  real :: user_lon0 = user_lon_min
  real :: user_lon1 = user_lon_max
  real :: user_lat0 = user_lat_min
  real :: user_lat1 = user_lat_max

  real              :: radar(ii,jj)

  character(len=7)  :: ifile="in_data"
  character(len=7)  :: ofile="outdata"

  integer :: ix, jy
  integer :: lon_min, lon_max, lat_min, lat_max, user_ii, user_jj

!Check the user setting
  if (user_lon0 .lt. lon0) then
    print *, "Your minimum lon is too small!"
    goto 980
  endif
  if (user_lon1 .gt. lon0+ii*dlon) then
    print *, "Your maximum lon is too large!"
    goto 980
  endif
  if (user_lat0 .lt. lat0) then
    print *, "Your minimum lat is too small!"
    goto 980
  endif
  if (user_lat1 .gt. lat0+jj*dlat) then
    print *, "Your maximum lat is too large!"
    goto 980
  endif

!Read the data
  open(10,file=ifile,form='unformatted',access='direct',status='old',recl=ii*jj*4)
    read(10,rec=1) ((radar(ix,jy),ix=1,ii),jy=1,jj)
  close(10)

!Extract the data with user setting
  !detect the extract condition
  lon_min = max(int((user_lon0-lon0)/dlon),1)
  lon_max = min(int((user_lon1-lon0)/dlon) + 1,ii)
  lat_min = min(jj - int((user_lat0-lat0)/dlat),jj)
  lat_max = max(jj - int((user_lat1-lat0)/dlat) - 1,1)
  user_ii = lon_max - lon_min + 1
  user_jj = lat_min - lat_max + 1

  print *, "lon_min=", lon_min, lon_min*dlon+lon0
  print *, "lon_max=", lon_max, lon_max*dlon+lon0
  print *, "lat_min=", lat_min, (jj-lat_min)*dlat+lat0
  print *, "lat_max=", lat_max, (jj-lat_max)*dlat+lat0
  print *, "user_ii=", user_ii
  print *, "user_jj=", user_jj

  open(11,file=ofile,form='unformatted',access='direct',status='replace',recl=user_ii*user_jj*4)

    write(11,rec=1) ((radar(ix,jy),ix=lon_min,lon_max),jy=lat_min,lat_max,-1)

  close(11)

  open(12,file='grid_info',form='formatted',status='replace')
    write(12,*) user_ii
    write(12,*) user_jj
  close(12)

  goto 999

980 continue
  print *, "Error in readradar.f90"

999 continue

end
'''
#f90にユーザー設定値を入力
f90 = f90.replace("user_lon_min",f"{user_lon_min}d0")
f90 = f90.replace("user_lon_max",f"{user_lon_max}d0")
f90 = f90.replace("user_lat_min",f"{user_lat_min}d0")
f90 = f90.replace("user_lat_max",f"{user_lat_max}d0")

#Ssディレクトリに実行ファイルを作成
Ss_dir = f"{drive_home}/lib_add/Ss"
if not os.path.exists(Ss_dir): os.makedirs(Ss_dir)
Ss_readf90 = f"{Ss_dir}/readradar.f90"
p_new = pathlib.Path(Ss_readf90)
with p_new.open(mode='w') as f:
  f.write(f90)
exe_readradar = f"{Ss_dir}/readradar.exe"
!gfortran -fconvert=swap $Ss_readf90 -o $exe_readradar
%cd /content/

#********************************
# GPVデータの取得
# (取得先は京大生存圏DB、
#  http://database.rish.kyoto-u.ac.jp/)
# * * * * * * * * * * * * * * * *

#作業用フォルダに移動
%cd $work_dir

#共通URL
url_root = "http://database.rish.kyoto-u.ac.jp/arch/jmadata/data/jma-radar/synthetic/original"

#取得対象日毎の データ取得 解凍 保存先の用意
d_dir0 = d_dir
for d in date_list:

  #日付毎のフォルダの用意
  if flg_datefold == 1:
    d_dir1 = f"{d_dir0}/{d}"
    if not os.path.exists(d_dir1): os.makedirs(d_dir1)
    d_dir = d_dir1

  #年、月、日の取得セクション
  yr_user = d[0:4]
  mo_user = d[4:6]
  dy_user = d[6:8]

  #gif生成用配列
  Imgs_radars = []

  #時、分の生成セクション
  for hr in range(0,24):

    #日本標準時から世界標準時への変換
    if flg_jst == 1:
      dt_diff = datetime.timedelta(hours=9)
      dt_jst = datetime.datetime(year=int(yr_user), month=int(mo_user), day=int(dy_user), hour=int(hr))
      dt_utc = dt_jst - dt_diff
      yr = str(dt_utc.year)
      mo = str(dt_utc.month).zfill(2)
      dy = str(dt_utc.day).zfill(2)
      h0 = str(dt_utc.hour).zfill(2)
    else:
      yr = yr_user
      mo = mo_user
      dy = dy_user
      h0 = str(hr).zfill(2)

    for mi in range(0,6):

      #URL生成 
      url = f"{url_root}/{yr}/{mo}/{dy}/Z__C_RJTD_{yr}{mo}{dy}{h0}{mi}000_RDR_JMAGPV__grib2.tar"

      #既得ファイルの確認
      d_file_tar = f"{d_dir}/Z__C_RJTD_{yr}{mo}{dy}{h0}{mi}000_RDR_JMAGPV__grib2.tar"
      if not os.path.exists(d_file_tar):
        #データ取得セクション(d_dir に保存)
        !wget -P $d_dir $url
      else:
        print (f"{d_file_tar} already downloaded!")

      #解凍済みファイルの確認
      g_file = f"{d_dir}/Z__C_RJTD_{yr}{mo}{dy}{h0}{mi}000_RDR_JMAGPV_Ggis1km_Prr10lv_ANAL_grib2.bin"
      g2file = f"{d_dir}/Z__C_RJTD_{yr}{mo}{dy}{h0}{mi}000_RDR_JMAGPV_Gll2p5km_Phhlv_ANAL_grib2.bin"
      if not os.path.exists(g_file):
        #解凍
        with tarfile.open(d_file_tar,'r') as tf:
         tf.extractall(path=d_dir)
      else:
        print (f"{d_file_tar} already unziped with tar command!")

      #grib形式ファイルの切り出し
      b_file = f"{d_dir}/Z__C_RJTD_{yr}{mo}{dy}{h0}{mi}000_RDR_JMAGPV_Ggis1km_Prr10lv_ANAL.bin"
      if not os.path.exists(b_file):
        #grib形式ファイルの切り出し実行
        %wgrib2 $g_file -order we:ns -no_header -bin {b_file}
      else:
        print (f"{g_file} already done(wgrib2)!")

      #実行
      %cp "{b_file}" "in_data" #シンボリックリンクに替えたいが偶にコマンドが使用不可になってしまう。
      !$exe_readradar

      #低容量化モード
      if flg_foldsize == 1:
        %rm $d_file_tar $g_file $g2file $b_file

      %rm in_data
      with open('grid_info','r') as f:
        user_ii = f.readline()
        user_ii = user_ii.rstrip()
        user_jj = f.readline()
        user_jj = user_jj.rstrip()
      %rm grid_info

#（https://qiita.com/OSAKO/items/ef042f80ec63dd288225 のほぼコピー）
      #↓ルックアップテーブル作成
      def lookup_table(start1, end1, step1, start2, end2, step2):
          keys = []
          values = []
          for i in np.arange(start1, end1, step1):
              i = str(round(i, 2))
              keys.append(i)
          for j in np.arange(start2, end2, step2):
              j = round(j, 2)
              values.append(j)
          d = dict(zip(keys, values))
          return d
      
      class Radar_echo:
          def __init__(self):
              f = open(f"{work_dir}/outdata", mode="rb") #切り出したデータを読み込んでから配列変換
              echo = np.fromfile(f, dtype="float32",sep="").reshape(int(user_jj),int(user_ii))
              #とりあえず0,0.1,260のデータ代表値を降水強度へ変換
              echo = np.where(echo < 0, 0, echo)
              echo = np.where(echo == 0.1, 0.1, echo)
              self.echo = np.where(echo == 260, 256, echo)
              
          def lut_to_echo(self):
              d1 = lookup_table(0.25, 2.05, 0.1,0.2, 2.0, 0.1)
              d2 = lookup_table(2.13, 5.13, 0.25, 2.0, 4.95, 0.25)
              d3 = lookup_table(5.25, 10.25, 0.5, 5.0, 10.0, 0.5)
              d4 = lookup_table(10.5, 180.5, 1.0, 10, 180, 1.0)
              d5 = lookup_table(181, 257, 2.0, 180, 256, 2.0)

              d1.update(d2)
              d1.update(d3)
              d1.update(d4)
              d1.update(d5)
              #ルックアップテーブルをもとに降水強度へ変換
              for k, v in d1.items():
                  self.echo = np.where(self.echo == float(k), v, self.echo)
              
          def draw(self):
              #東西・南北のグリッドを作成
              lon = np.round(np.linspace(float(user_lon_min), float(user_lon_max), int(user_ii)), 4)
              lat = np.round(np.linspace(float(user_lat_min), float(user_lat_max), int(user_jj)), 4)
              X, Y = np.meshgrid(lon,lat)

              fig = plt.figure(dpi=100)
              cmap = plt.get_cmap('jet')
              cmap.set_under("w")
              cmap.set_over("firebrick")

              #Basemapによる描画
              m = Basemap(projection="cyl", resolution="i", llcrnrlat=f"{user_lat_min}",urcrnrlat=f"{user_lat_max}", llcrnrlon=f"{user_lon_min}", urcrnrlon=f"{user_lon_max}")
              m.drawcoastlines(color='black')
              m.drawmeridians(np.arange(0, 360, lon_dx), labels=[True, False, False, True],linewidth=0.1)
              m.drawparallels(np.arange(-90, 90, lat_dy), labels=[True, False, True, False],linewidth=0.1)
              m.readshapefile(border_shape, 'prefectural_bound2', color='gray', linewidth=.5)
              im = plt.contourf(X,Y, self.echo, levels, cmap=cmap, extend='both')
              cb = m.colorbar(im, "right", size="2.5%")
              cb.set_label('mm/hr')
              if flg_jst == 1:
                plt.title(f"Radar {d} {str(hr).zfill(2)}:{mi}0JST")
                base = f"Radar_{d}{str(hr).zfill(2)}{mi}0jst.png"
              else:
                plt.title(f"Radar {d} {str(hr).zfill(2)}:{mi}0UTC")
                base = f"Radar_{d}{str(hr).zfill(2)}{mi}0utc.png"
              plt.savefig(base)

      if __name__ == '__main__':
          echo = Radar_echo()
          echo.lut_to_echo()
          echo.draw()

      #データの移動・整理
      #data_name = f"{d_dir}/Radar_{d}{hr.zfill(2)}{mi}0.dat"
      #%mv $work_dir/outdata $d_dir/$data_name #必要な人は行頭の#を外す
      %rm $work_dir/outdata #必要な人は行頭の#を付ける
      if flg_jst == 1:
        fig_name = f"Radar_{d}{str(hr).zfill(2)}{mi}0jst.png"
      else:
        fig_name = f"Radar_{d}{str(hr).zfill(2)}{mi}0utc.png"
      %mv $work_dir/$fig_name $d_dir
      fig_name = f"{d_dir}/{fig_name}"
      #gif生成リストに追加
      Imgs_radars.append(fig_name)

  #gifの作成
  gif_name = f"{d_dir}/Radar_{d}.gif"
  frames_radar = []
  for i in range(len(Imgs_radars)):
    img = Image.open(Imgs_radars[i])
    frames_radar.append(img)
  frames_radar[0].save(gif_name,save_all=True,append_images=frames_radar[1:],duration=dur_time,loop=0)

  #メールの送信
  if use_mail == 1:
    #メールタイトル
    subject = f"Radar_get {d} end."
    #メール本文（html形式）
    body = f"※本メールに覚えの無い方は、お手数ですが {gmail_account} までご連絡ください。<br><br>"
    body = f"{body} Radar_get による {d} のデータ取得・処理が完了しました。<br>保存先：{d_dir}<br>対象日：{d}"
    #メール送信設定
    msg = MIMEText(body, "html")
    msg["Subject"] = subject
    msg["To"] = mail_to
    msg["From"] = str(Header(f"'{send_name}<{gmail_account}>'"))
    #メールサーバーへのアクセス
    server = smtplib.SMTP_SSL("smtp.gmail.com", 465, context=ssl.create_default_context())
    server.login(gmail_account, gmail_password)
    #メールの送信
    server.send_message(msg)
    print("Send.") 
     
  time.sleep(5)

#終了処理
%rm -rf $work_dir
```

# ユーザー毎の設定値
本資料に公開するソースコード中でユーザーが編集すべき箇所は、
`ユーザーセッティング（ここから）`と
`ユーザーセッティング（ここまで）`
で囲われている部分のみです。
それぞれの設定方法について以下に簡単に説明します。

## ユーザー名の登録
`user_name`には任意の名前を入力してください。空欄はNGです。
## 取得対象日の設定
`date_list`には作成したい日にちを入力してください。
8桁(yyyymmdd)で入力する必要があります。
また、それぞれ日にちは""で囲ってください。
複数日を設定する場合には,で区切ります。
(例) date_list = ["20200601","20200827"]
### 取得対象日の標準時設定
`date_list`の各日を日本標準時(JST(UTC+9))として扱う場合には、
`flg_jst = 1`としてください。
1以外を選択した場合は、世界標準時(UTC)が採用されます。
（基本的には日本標準時を採用した方が便利かと思います。）
## 取得対象領域の設定
選択可能な領域は元データ（東経118.0~150.0, 北緯20.0~48.0）の範囲の内側です。
描画したい領域の東経（最小、最大）、北緯（最小、最大）をそれぞれ、
`user_lon_min`, `user_lon_max`, `user_lat_min`, `user_lat_max`, 
に入力してください。
また、必ず小数点を含む必要があります。
## 出力先の設定
任意のGoogleDriveに出力します。
`o_dir`にはGoogleDriveの`マイドライブ`配下の希望パスを入力してください。
(例) マイドライブ/data/JMA/RADARに出力したい場合は、
o_dir = 'data/JMA/RADAR'
### 日にち毎のフォルダへの出力（推奨）
更にこの`o_dir`配下に日にち毎のフォルダを作成したい場合は、
`flg_datefold = 1`としてください。
（後述のメール通知機能を使用する場合は`flg_datefold = 1`である必要があります。）
## 地図の設定
### 県境・市区町村境界線の表示
`flg_border = `で設定します。
0: 県境なし（海岸線のみ）、1: 県境あり、2: 市区町村境界あり
### 経線間隔（度）
`lon_dx = `で設定します。関東域であれば0.5くらいがちょうどいい。
### 経線間隔（度）
`lat_dy = `で設定します。関東域であれば0.5くらいがちょうどいい。
## 降水強度のカラースケール
`levels = []`で設定します。
配色は、左端以下が白抜きになり、以降は順に青～(虹)～赤としています。
単位は`mm/hr`です。

## gifの設定
gif動画での1枚当たりの表示時間を`dur_time`で設定します。単位はミリ秒です。

## 低フォルダ容量化の設定
`flg_foldsize = `で設定します。
低容量化を行う場合は1を、行わない場合は1以外を入力してください。
※元データの展開後の容量が1タイムステップあたり約33.1MBにもおよびます。（1日まるっとやると約4.77GB...）
※そのため展開後の元データを随時削除する方針にしています。ただ、元データを再利用したい場合等、空き容量との天秤で効率化を図る場合はご自由に。

## メール通知の設定(`flg_datefold = 1`のときのみ有効)
このプログラムは1タイムステップあたり約15秒程度かかります。（※出力領域範囲に因ります。）
そのため、実行から終了までにそれなりの時間がかかってしまいます。また、複数日を指定して実行した場合には、経過報告が欲しかったりするものです。そのため、1日分毎に終了報告をメールで通知するようにしています。
この機能を使用する場合には、`use_mail = 1`としてください。
また、`use_mail = 1`とした際には、
送信先を`mail_to = `に、
件名を`send_name = `に入力してください。
さらに、送信用アドレスの設定も必要です。
`gmail_account = `に送信用メールアドレス（gmail）を、
`gmail_passward = `にそのパスワードを入力してください。
※gmailを外部からこのような形で扱うためには、そのアカウントのセキュリティ設定を下げる必要があります。できるだけ、専用の捨て垢を用意しましょう。
※セキュリティ設定を下げる方法は<a href="https://news.mynavi.jp/article/zeropython-51/">こちらのページ</a>に詳しいです。

## wgrib2の設定
よっぽどのことが無い限り編集不要です。ただ、wgrib2のバージョンに制限を受けるような作業を行う場合には、`wgrb_ver = `で設定可能です。
通常は`wgrb_ver = wgrb2.tgz.v3.0.2`としています。
※wgrib2が何のことかわからない人は気にせずにそのまま進めましょう。

# その他個別に設定したいものなど
本項目は随時更新していく予定です。
##対象時刻の設定
現在は0時から23時50分まで全てを対象としていますが、そんなに長い時間はいらないよ、って人は、以下の部分を編集してください。

```python
  #時、分の生成セクション
  for hr in range(0,24):
```

このhrが時刻に関する変数です。これが0から24になっているので、デフォルトでは0時から23時50分までが対象となっています。6時から18時のデータが必要であれば、for hr in range(6,17)とすれば、6時から17時50分までのものになります。

# エラーが生じたとき
case by caseですが、よく生じるエラーの1つにXXX not foundやXXX not exist等があります。これらの場合は、基本的にドライブのファイルへのアクセスに失敗している時なので、以下の手順で試してみてください。
##その1：ランタイムの再起動
上部タブに「ランタイム」という項目があるので、そこをクリックすると色々選べます。そこからランタイムの再起動を実行してみてください。

## その2：wgrib2の再インストール
その1で解決しない場合には、一度wgrib2を消すのが手っ取り早いです。ドライブ側でwgrib2に関係するフォルダを削除します。（本記事通りの名前であれば、lib_add/wgrib2があるはずなので、このwgrib2を削除してください。）削除後、一度ドライブを再読み込みしてから、再度プログラムを実行してみてください。

## その3:諸々やり直してみる
途中でエラーを繰り返していると、意図しない不要な（邪魔な）ファイル等が生成してしまっている場合があります。関連するフォルダを全削除してみるのが最終手段です。（削除する前に、必要なデータは疎開させておくこと。）
関連するフォルダとは、`lib_add`と`data/JMA`です。

# 参考
・データ入手先
http://database.rish.kyoto-u.ac.jp/arch/jmadata/
・気象レーダーデータの描画について
https://qiita.com/OSAKO/items/ef042f80ec63dd288225
・メール送信機能について
https://news.mynavi.jp/article/zeropython-51/