#!/usr/bin/env ruby

=begin

=gpcat

複数ファイルに対して時空間方向に接続して X 平均を取る. 
指定されたディレクトリ以下の time* というディレクトリに対して再帰的に実行. 

==USAGE

  % arare-addmean --dir Directory


==OPTIONS

      --help         : print this message. 
      --dir dirvar   : directory name (required).

==HISTORY

  2009/04/23  K Sugiyama (created)

=end

require "numru/netcdf"
require "numru/dcl"
require "numru/ggraph"
require "getoptlong"
include NumRu

###
###引数処理
###
parser = GetoptLong.new
parser.set_options(
                   ###    global option   ###
                   ['--dir',  "-d", GetoptLong::REQUIRED_ARGUMENT],
                   ["--help", "-h", GetoptLong::NO_ARGUMENT ]
                   )
begin
  parser.each_option do |name, arg|
    eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_')} = '#{arg}'" 
  end
    rescue
  exit(1)
end

if $OPT_HELP then
  help
  exit(0)
end  

###
### 初期設定
###
coords = ["x", "y", "z", "t", "s", "alt", "t_nv", "t_bnds"] # 軸の設定
dir = "#{$OPT_dir}"           # トップディレクトリ
subdir = "time*"

# ファイル置き場
meanfiles = "meanfiles"	 
submeanfiles = "#{meanfiles}/#{dir.sub("./","")}"
Dir::mkdir(meanfiles) unless FileTest.exist?(meanfiles)
Dir::mkdir(submeanfiles) unless FileTest.exist?(submeanfiles)

# 変数名の保管用
varnames  = Array.new
varnames2 = Array.new

###
### 水平平均を行う
###   水平平均された量に関しては, ファイル名を変更するだけ.
###   MPI 版の出力は既に 1 ファイルにまとまっているものと仮定する. 
###

Dir.glob("#{dir}/#{subdir}").each{ |subdir|
  p "TOPDIR: #{dir}, SUBDIR: #{subdir}"

  # ファイル名を保管する配列を用意する. 
  ncfiles = Array.new 
  Dir::glob("#{subdir}/*").each{ |file|
    next unless  /.*\.nc/ =~ file 
    next if /restart/ =~ file      # リスタートファイルは対象外.
    
    # 並列計算の場合は node* を外して保管
    file2 = File::basename(file) 
    unless /^([a-z,A-Z,1-9]+)_(.+)_rank(\d\d\d\d\d\d).nc$/=~ file2
      ncfiles.push(file)
    end
  }
  
  # 逐次版と並列版に対して処理を行う. 
  # 並列計算を行っていても, 解析は 1 つのファイルにまとめて行うことが多いので, 
  # あえて逐次版と並列版の両方の結果に対して実行する. 
  ncfiles.each{ |ncfile|
    p ncfile
    GDir.top = '/'
    gdir = GDir.new(File.expand_path(ncfile))
      
    gdir.list_data_v.each{|gd| 
      vars = gd.split(/\t/)
      next if coords.index(vars[0]) # 軸定義の場合は除外.
      varnames.push(vars[0])        # 変数名を保存
      output = "#{submeanfiles}/#{File::basename(subdir)}_#{vars[0]}.nc"
      
      # 既に存在する場合
      if FileTest.exist?(output)
        # 既に存在していても mtime が古い場合はスキップしない.
        mtime = File.mtime(output)  - File.mtime(ncfile) 
        next if mtime > 0
        p "#{ncfile}, #{File.mtime(ncfile)}, #{output}, #{File.mtime(output)}"
      end
      
      p "#{ncfile}, #{vars[0]}, #{vars[1]}"
      gturl = "#{ncfile}@#{vars[0]}"
      gphys = GPhys::IO.open_gturl(gturl)
      gphys = gphys.mean('x') if /x\=/ =~ vars[1]  # x 軸が存在する場合
      gphys = gphys.mean('y') if /y\=/ =~ vars[1]  # y 軸が存在する場合
      
      outncfile=NetCDF.create(output)
      GPhys::IO.write( outncfile, gphys )          # Output GPhys variable
      # NetCDF_Conventions.add_history(outncfile, File.basename($0)+" "+ARGV[0])
      outncfile.close
      p "#{gturl} is written to #{output}."
    }
  }
}


###
### 時間方向に接続する. 
### ファイル名が正しく時系列に並んでいることを前提とする. 
###
varnames.uniq!
varnames.each{ |var|
  p "VAR: #{var}"

  output = "#{submeanfiles}/AllData_#{var}.nc"

  ncfiles2 = Dir::glob("#{submeanfiles}/time*_#{var}.nc").sort

  # 既に存在する場合. 
#  File.unlink(output) if FileTest.exist?(output)
  if FileTest.exist?(output)
    # 既に存在していても mtime が古い場合はスキップしない.
    mtime = File.mtime(output)  - File.mtime(ncfiles2[0]) 
    p "#{mtime}, #{output}(#{File.mtime(output)}), #{ncfiles2[0]}(#{File.mtime(ncfiles2[0])})"
    next if mtime > 0
  end

  unless ncfiles2.size == 1 || /BasicZ/ =~ var
    gphys3 = GPhys::IO.open(ncfiles2, var)
    print "GPhys variable '#{var}' in NetCDF files, " + ncfiles2.join(', ') +", was opened successfully.\n"
  else
    gphys3 = GPhys::IO.open(ncfiles2[0], var)
    print "GPhys variable '#{var}' in NetCDF files, " + ncfiles2[0] +", was opened successfully.\n"
  end
    
  outncfile=NetCDF.create(output)
  GPhys::IO.write( outncfile, gphys3 )
  p "#{var} is written to #{output}."
  outncfile.close

} 
