# 熱, 水収支を計算します
# 
# 履歴
# 2010/03/26  納多 哲史   物理量の名前を文字変数で与えられるようにした
# 2009/10/02  納多 哲史   北半球と南半球で領域が重複していたバグを修正
# 2009/10/01  納多 哲史   とりあえず完成
# 2009/09/24  納多 哲史   作成


require "numru/ggraph"
include NumRu

ana_start_time = 1000
ana_end_time   = 2000

name_SSR = "SSRA"
name_SLR = "SLRA"
name_OSR = "OSRA"
name_OLR = "OLRA"
name_Sens = "SensA"
name_Evap = "EvapA"
name_Rain = "Rain"


# 各変数について
# * 調べる範囲
#   * ある点の量
#   * 半球平均 (東西南北)
# * 計算する量
#   * 大気の熱収支
#   * 大気の水収支

# 解析対象となるファイルの場所
prefix = '.'

# debug
#prefix = '/home/noda/work/dcpam/dcpam5/practice/090629_test_reprod-morikawa_SR090_1Omega_nonSR'
#prefix = '/home/noda/work/dcpam/dcpam5/practice/090605_test_reprod-morikawa_SR090_0.5Omega'


def help()
  print <<EOM

  Usage:

    ruby #{$0} [option]

  Options:

    --range_time val:val   range of time [default 1000:2000]
    --prefix path          set prefix of files [default "."]
    -h, --help             show this help

EOM
end

def get_range(str)
  str_a = str.split(/\:/)
  if str_a.size == 2
    range_start = eval(str_a[0])
    range_end   = eval(str_a[1])
    return range_start, range_end
  else
    puts "ERROR: illegal format!\n"
    help
    exit 10
  end
end

# 1 点を解析する時の場所を [経度, 緯度] で指定
points = [
          [  0,  0],
          [ 90,  0],
          [180,  0],
          [270,  0],
          [ 90, 30],
          [270, 30],
          [ 90, 60],
          [270, 60],
        ]


var_list = [
             name_SSR,
             name_SLR,
             name_OSR,
             name_OLR,
             name_Sens,
             name_Evap,
             name_Rain
           ]


# 処理開始

# コマンドライン引数処理

while ARGV.size > 0
  case ARGV[0]
  when "--range_time"
    ARGV.shift
    ana_start_time, ana_end_time = get_range(ARGV[0])
  when "--prefix"
    ARGV.shift
    prefix = ARGV[0]
  when "-h", "--help"
    help
    exit 0
  else
    puts "ERROR: unknown argument!\n"
    help
    exit 20
  end
  ARGV.shift
end


# HTML のヘッダを出力
print <<EOM
<html>
<head>
  <title>Budget</title>
<head>
<body>

<h1>Budget</h1>

<ul>
  <li>Time range: #{ana_start_time} - #{ana_end_time} (day)
  <li>Unit is W m-2.
  <li>Upward is positive.
  <li>(Heat Budget) = (OSR + OLR) + (SSR + SLR) + Sens + Rain
  <li>(Water Budget) = EVap - Rain
  <li>(Surface Budget) = SSR + SLR + Sens + Evap
  <li>(Top Budget) = OSR + OLR
</ul>

<table border=1 cellpadding=5>
EOM

puts "<tr>"
puts "<td>" + "Point or Range" + "</td>"
for varname in var_list
  puts "<td align=right>" + varname + "</td>"
end
puts "<td align=right>" + "Heat Budget" + "</td>"
puts "<td align=right>" + "Water Budget" + "</td>"
puts "<td align=right>" + "Surface Budget" + "</td>"
puts "<td align=right>" + "Top Budget" + "</td>"
puts "</tr>"


path = File.join(prefix, var_list[0] + ".nc")

lon_na = GPhys::IO.open(path, 'lon').data.val
lat_na = GPhys::IO.open(path, 'lat').data.val
#lon_weight_na = GPhys::IO.open(path, 'lon_weight').data.val
lat_weight_na = GPhys::IO.open(path, 'lat_weight').data.val

lat = GPhys::IO.open(path, 'lat')
lat_weight = GPhys::IO.open(path, 'lat_weight')

nlon = lon_na.length
nlat = lat_na.length
ntime = GPhys::IO.open(path, 'time').cut("time"=>ana_start_time..ana_end_time).val.length



# 範囲の平均を取る時の場所を [経度開始, 経度終了, 緯度開始, 緯度終了] で指定.
# 注意: Gphys は指定された値がないときは近い値を取ってくるので, 
#       半球平均などの際のダブルカウントに注意.
ranges = [
  [              0,   lon_na[nlon-1]  ,            -90,               90 ],   # 全球
  [              0,   lon_na[nlon-1]  , lat_na[nlat/2],               90 ],   # 北半球
  [              0,   lon_na[nlon-1]  ,            -90, lat_na[nlat/2-1] ],   # 南半球
  [              0,   lon_na[nlon/2-1],            -90,               90 ],   # 東半球
  [ lon_na[nlon/2],   lon_na[nlon-1]  ,            -90,               90 ]    # 西半球
         ]



var = Hash.new

# ファイルの読み込み
for varname in var_list
  path = File.join(prefix, varname + ".nc")
# GPhys クラスの変数をハッシュに格納
  var[varname] = GPhys::IO.open( File.join(prefix, varname + ".nc"), varname).cut("time"=>ana_start_time..ana_end_time)
end




ave    = Hash.new
stddev = Hash.new



# 領域平均
for range in ranges

  puts "<tr>"

  x_start = range[0]
  x_end   = range[1]
  y_start = range[2]
  y_end   = range[3]

  puts "<td>(" + sprintf("%#.1f", x_start) + ":" + sprintf("%#.1f", x_end) + ", " + sprintf("%#.1f", y_start) + ":" + sprintf("%#.1f", y_end) + ")</td>"

  for varname in var_list

    tmp = var[varname].cut("lon"=>x_start..x_end, "lat"=>y_start..y_end)
    tmp = tmp.mean("lon")

    tmp_ave = 0.0
    for y in lat.cut("lat"=>y_start..y_end).val
      weight   = lat_weight.cut("lat"=>y).val.to_f
#      weight   = lat_weight.cut("lat"=>y).val
      tmp_ave += tmp.cut("lat"=>y) * weight
    end

    # 全球平均でも {南, 北} 半球平均でも重みが同じになるように補正
    if lat.cut("lat"=>y_start..y_end).val.size == nlat
      tmp_ave /= 2.0
    end

    ave[varname]    = tmp_ave.mean("time")
#    stddev[varname] = tmp_ave.stddev("time")

    puts "<td align=right>" + sprintf("%#.3f", ave[varname].val) + "</td>"

  end

  total_heat = (ave[name_OSR] + ave[name_OLR]) \
                + (ave[name_SSR] + ave[name_SLR]) + ave[name_Sens] + ave[name_Rain]
#  total_heat = (ave[name_SLR] - ave[name_OLR]) + ave[name_Sens] + ave[name_Rain]
  total_wat  = ave[name_Evap] - ave[name_Rain]
  total_surf = ave[name_SSR] + ave[name_SLR] + ave[name_Sens] + ave[name_Evap]
  total_top  = ave[name_OSR] + ave[name_OLR]

  puts "<td align=right>" + sprintf("%#.3f", total_heat.val) + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_wat.val)  + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_surf.val)  + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_top.val)  + "</td>"

  puts "</tr>"
  puts ""

end




# 指定された点での解析
for point in points

  puts "<tr>"

  point_lon = point[0]
  point_lat = point[1]

  puts "<td>(" + point_lon.to_s + ", " + point_lat.to_s + ")</td>"

  for varname in var_list
    tmp      = var[varname].cut("lon"=>point_lon, "lat"=>point_lat)

    ave[varname]    = tmp.mean("time")
#    stddev[varname] = tmp.stddev("time")

    puts "<td align=right>" + sprintf("%#.3f", ave[varname].val) + "</td>"

  end

  total_heat = (ave[name_OSR] + ave[name_SSR]) \
     + (ave[name_SLR] + ave[name_OLR]) + ave[name_Sens] + ave[name_Rain]
#  total_heat = (ave[name_SLR] - ave[name_OLR]) + ave[name_Sens] + ave[name_Rain]
  total_wat  = ave[name_Evap] - ave[name_Rain]
  total_surf = ave[name_SSR] + ave[name_SLR] + ave[name_Sens] + ave[name_Evap]
  total_top  = ave[name_OSR] + ave[name_OLR]
  puts "<td align=right>" + sprintf("%#.3f", total_heat.val) + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_wat.val)  + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_surf.val)  + "</td>"
  puts "<td align=right>" + sprintf("%#.3f", total_top.val)  + "</td>"

  puts "</tr>"
  puts ""

end



# html を閉じる
puts "</table>"
puts "</html>"


__END__





