Skip to content

Instantly share code, notes, and snippets.

@komasaru
Last active June 29, 2018 05:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/44357dc853325cab04de7694b4b3b6e6 to your computer and use it in GitHub Desktop.
Save komasaru/44357dc853325cab04de7694b4b3b6e6 to your computer and use it in GitHub Desktop.
Ruby script to generate csv data from IERS's EOP.
#! /usr/local/bin/ruby
# coding: utf-8
#---------------------------------------------------------------------------------
#= IERS の Buttelin A テキストデータから EOP(Polar Motion etc.) CSV ファイルを生成
# * 予め [こちら](ftp://ftp.iers.org/products/eop/rapid/) からダウンロードして
# おいたものを使用する。
# (IAU 2000A 章動理論によるデータ finals2000A.all", "finals2000A.daily")
# * 1日のデータに速報値(区分"I")と確定値がある場合は、確定値を優先。
# * 2ファイルで重複する日付のデータは "finals2000A.daily" を優先。
# * 取得する項目:
# date, flag_pm, pm_x, pm_x_e, pm_y, pm_y_e,
# flag_dut, dut1, dut1_e, lod, lod_e,
# flag_nut, nut_x, nut_x_e, nut_y, nut_y_e
#
# date name version
# 2018.06.25 mk-mode.com 1.00 新規作成
#
# Copyright(C) 2018 mk-mode.com All Rights Reserved.
#---------------------------------------------------------------------------------
# 引数 : なし
#---------------------------------------------------------------------------------
#++
require "open-uri"
class GetEopCsv
USAGE = "[USAGE] ./get_eop_csv.rb"
FILE_A = "./file/finals2000A.all"
FILE_D = "./file/finals2000A.daily"
FILE_CSV = "data/eop.csv"
re_str = '^(.{6}) (.{8}) ([IP ]) (.{9})(.{9}) (.{9})(.{9}) '
re_str += '([IP ])(.{10})(.{10}) (.{7})(.{7}) '
re_str += '([IP ]) (.{9})(.{9}) (.{9})(.{9})'
re_str += '(.{10})(.{10})(.{11})(.{10})(.{10})\s*$'
RE_0 = Regexp.new(re_str)
RE_1 = Regexp.new('.{2}')
RE_2 = Regexp.new('^\s+$')
def initialize
@data = Hash.new
end
def exec
get_data("A") # 過去全データ取得
get_data("D") # 日次データ取得
write_csv # CSV 保存
rescue => e
$stderr.puts "[#{e.class}] #{e.message}"
e.backtrace.each { |tr| $stderr.puts "\t#{tr}"}
exit 1
end
private
# ------------------------------------
# データ取得
#
# @param: div ("A": ALLデータ, "D": DAILYデータ)
# ------------------------------------
def get_data(div)
file = div == "A" ? FILE_A : FILE_D
File.open(file, "r:utf-8") do |f|
while line = f.gets
line.chomp!
m = line.scan(RE_0)[0]
flag_pm, flag_dut, flag_nut = m[2], m[7], m[12]
flag_pm.sub!(RE_2, "")
flag_dut.sub!(RE_2, "")
flag_nut.sub!(RE_2, "")
break if div == "A" &&
flag_pm == "P" &&
flag_dut == "P" &&
flag_nut == "P"
year, month, day = m[0].scan(RE_1).map(&:to_i)
year = year > 72 ? year + 1900 : year + 2000
date = "%04d-%02d-%02d" % [year, month, day]
mjd = m[1].to_f
# Polar Motion
pm_x, pm_x_e, pm_y, pm_y_e = m[3, 4].map do |a|
RE_2 =~ a ? nil : a.to_f
end
pm_x_f, pm_y_f = m[17, 2].map do |a|
RE_2 =~ a ? nil : a.to_f
end
flag_pm = "F" if pm_x_f && pm_y_f
pm_x, pm_x_e = pm_x_f, 0.0 if pm_x_f
pm_y, pm_y_e = pm_y_f, 0.0 if pm_y_f
# UT1 - UTC, LOD
dut1, dut1_e, lod, lod_e = m[8, 4].map do |a|
RE_2 =~ a ? nil : a.to_f
end
dut1_f = RE_2 =~ m[19] ? nil : m[19].to_f
flag_dut, dut1, dut1_e = "F", dut1_f, 0.0 if dut1_f
# Nutation
nut_x, nut_x_e, nut_y, nut_y_e = m[13, 4].map do |a|
RE_2 =~ a ? nil : a.to_f
end
nut_x_f, nut_y_f = m[20, 2].map do |a|
RE_2 =~ a ? nil : a.to_f
end
flag_nut = "F" if nut_x_f && nut_y_f
nut_x, nut_x_e = nut_x_f, 0.0 if nut_x_f
nut_y, nut_y_e = nut_y_f, 0.0 if nut_y_f
@data[mjd] = [
date, flag_pm, pm_x, pm_x_e, pm_y, pm_y_e,
flag_dut, dut1, dut1_e, lod, lod_e,
flag_nut, nut_x, nut_x_e, nut_y, nut_y_e
]
end
end
rescue => e
raise
end
# ------------------------------------
# CSV 保存
# ------------------------------------
def write_csv
open(FILE_CSV, "w:utf-8") do |f|
@data.each do |k, v|
f.puts "#{v[0]},#{k}," + v[1..-1].map(&:to_s).join(",")
end
end
rescue => e
raise
end
end
GetEopCsv.new.exec if __FILE__ == $0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment