module Cdo

CDO calling mechnism

Private Class Methods

boundaryLevels(args) click to toggle source
Addional operotors:
# File lib/cdo_lib.rb, line 324
def Cdo.boundaryLevels(args)
  ilevels         = Cdo.showlevel(:input => args[:input])[0].split.map(&:to_f)
  bound_levels    = Array.new(ilevels.size+1)
  bound_levels[0] = 0
  (1..ilevels.size).each {|i| 
    bound_levels[i] =bound_levels[i-1] + 2*(ilevels[i-1]-bound_levels[i-1])
  }
  bound_levels
end
call(cmd) click to toggle source
# File lib/cdo_lib.rb, line 108
def Cdo.call(cmd)
  if (State[:debug])
    puts '# DEBUG ====================================================================='
    pp Cdo.env unless Cdo.env.empty?
    puts 'CMD: '
    puts cmd
    puts '# DEBUG ====================================================================='
  end
  stdin, stdout, stderr, wait_thr = Open3.popen3(Cdo.env,cmd)

  {
    :stdout     => stdout.read,
    :stderr     => stderr.read,
    :returncode => wait_thr.value.exitstatus
  }
end
checkCdo() click to toggle source

test if @@CDO can be used

# File lib/cdo_lib.rb, line 266
def Cdo.checkCdo
  unless hasCdo?(@@CDO)
    warn "Testing application #@@CDO is not available!"
    exit 1
  else
    puts "Using CDO: #@@CDO"
    puts IO.popen(@@CDO + " -V").readlines
  end
  return true
end
debug() click to toggle source
# File lib/cdo_lib.rb, line 218
def Cdo.debug
  State[:debug]
end
debug=(value) click to toggle source
# File lib/cdo_lib.rb, line 215
def Cdo.debug=(value)
  State[:debug] = value
end
env() click to toggle source
# File lib/cdo_lib.rb, line 106
def Cdo.env; State[:env]; end
env=(envHash) click to toggle source
# File lib/cdo_lib.rb, line 103
def Cdo.env=(envHash)
  State[:env] = envHash
end
forceOutput() click to toggle source
# File lib/cdo_lib.rb, line 224
def Cdo.forceOutput
  State[:forceOutput]
end
forceOutput=(value) click to toggle source
# File lib/cdo_lib.rb, line 221
def Cdo.forceOutput=(value)
  State[:forceOutput] = value
end
getCdo() click to toggle source
# File lib/cdo_lib.rb, line 284
def Cdo.getCdo
  @@CDO
end
getOperators(force=false) click to toggle source
# File lib/cdo_lib.rb, line 68
def Cdo.getOperators(force=false)
  # Do NOT compute anything, if it is not required
  return State[:operators] unless (State[:operators].empty? or force)
  cmd       = @@CDO + ' 2>&1'
  help      = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
  if 5 >= help.size
    warn "Operators could not get listed by running the CDO binary (#{@@CDO})"
    pp help if Cdo.debug
    exit
  end
  # in version 1.5.6 the output of '-h' has changed
  State[:operators] = case 
                      when Cdo.version < "1.5.6"
                        (help[help.index("Operators:")+1].split + @@undocumentedOperators).uniq
                      when Cdo.version <= "1.7.0"
                        help[(help.index("Operators:")+1)..help.index(help.find {|v| v =~ /CDO version/}) - 2].join(' ').split
                      else
                        IO.popen(@@CDO + ' --operators').readlines.map {|l| l.split(' ').first}
                      end
end
getSupportedLibs(force=false) click to toggle source
# File lib/cdo_lib.rb, line 199
def Cdo.getSupportedLibs(force=false)
  return unless (State[:libs].nil? or force)
  _, _, stderr, _ = Open3.popen3(@@CDO + " -V")
  supported       = stderr.readlines.map(&:chomp)
  with            = supported.grep(/(with|Features)/)[0].split(':')[1].split.map(&:downcase)
  libs            = supported.grep(/library version/).map {|l| 
    l.strip.split(':').map {|l| 
      l.split.first.downcase
    }[0,2]
  }
  State[:libs] = {}
  with.flatten.each {|k| State[:libs][k]=true}
  libs.each {|lib,version| State[:libs][lib] = version}
end
hasCdo?(bin=@@CDO) click to toggle source
# File lib/cdo_lib.rb, line 258
def Cdo.hasCdo?(bin=@@CDO)
  return true if File.exists?(@@CDO) and File.executable?(@@CDO)
  ENV['PATH'].split(File::PATH_SEPARATOR).each {|path| 
    return true if File.exists?([path,bin].join(File::SEPARATOR))
  }
end
hasError(cmd,retvals) click to toggle source
# File lib/cdo_lib.rb, line 89
def Cdo.hasError(cmd,retvals)
  if (State[:debug])
    puts("RETURNCODE: #{retvals[:returncode]}")
  end
  if ( 0 != retvals[:returncode] )
    puts("Error in calling:")
    puts(">>> "+cmd+"<<<")
    puts(retvals[:stderr])
    return true
  else
    return false
  end
end
hasLib?(lib) click to toggle source
# File lib/cdo_lib.rb, line 298
def Cdo.hasLib?(lib)
  return Cdo.libs.has_key?(lib)
  return false
end
help(operator=nil) click to toggle source
# File lib/cdo_lib.rb, line 374
def Cdo.help(operator=nil)
  if operator.nil?
    puts Cdo.call([@@CDO,'-h'].join(' '))[:stderr]
  else
    operator = operator.to_s unless String == operator.class
    if Cdo.operators.include?(operator)
      puts Cdo.call([@@CDO,'-h',operator].join(' '))[:stdout]
    else
      puts "Unknown operator #{operator}"
    end
  end
end
libs() click to toggle source
# File lib/cdo_lib.rb, line 293
def Cdo.libs
  getSupportedLibs
  State[:libs]
end
libsVersion(lib) click to toggle source
# File lib/cdo_lib.rb, line 303
def Cdo.libsVersion(lib)
  unless Cdo.hasLib?(lib)
    raise ArgumentError, "Cdo does NOT have support for '#{lib}'"
  else
    if State[:libs][lib].kind_of? String
      return State[:libs][lib]
    else
      warn "No version information available about '#{lib}'"
      return false
    end
  end
end
loadCdf() click to toggle source
# File lib/cdo_lib.rb, line 189
def Cdo.loadCdf
  begin
    require "numru/netcdf_miss"
    include NumRu
  rescue LoadError
    warn "Could not load ruby's netcdf bindings. Please install it."
    raise
  end
end
log() click to toggle source
# File lib/cdo_lib.rb, line 231
def Cdo.log
  State[:log]
end
log=(value) click to toggle source
# File lib/cdo_lib.rb, line 227
def Cdo.log=(value)
  State[:log] = value
end
method_missing(sym, *args, &block) click to toggle source
# File lib/cdo_lib.rb, line 173
def Cdo.method_missing(sym, *args, &block)
  ## args is expected to look like [opt1,...,optN,:input => iStream,:output => oStream] where
  # iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))
  puts "Operator #{sym.to_s} is called" if State[:debug]
  if getOperators.include?(sym.to_s)
    io, opts = Cdo.parseArgs(args)
    if @@outputOperatorsPattern.match(sym)
      run(" -#{sym.to_s}#{opts} #{io[:input]} ",$stdout)
    else
      run(" -#{sym.to_s}#{opts} #{io[:input]} ",io[:output],io[:options],io[:returnCdf],io[:force],io[:returnArray],io[:returnMaArray])
    end
  else
    raise ArgumentError,"Operator #{sym.to_s} not found"
  end
end
openCdf(iFile) click to toggle source
# File lib/cdo_lib.rb, line 349
def Cdo.openCdf(iFile)
  Cdo.loadCdf unless State[:returnCdf] 
  NetCDF.open(iFile,'r+')
end
operators() click to toggle source
# File lib/cdo_lib.rb, line 288
def Cdo.operators
  Cdo.getOperators if State[:operators].empty?
  State[:operators]
end
parseArgs(args) click to toggle source
# File lib/cdo_lib.rb, line 161
def Cdo.parseArgs(args)
  # splitinto hash-like args and the rest
  operatorArgs = args.reject {|a| a.class == Hash}
  opts = operatorArgs.empty? ? '' : ',' + operatorArgs.join(',')
  io   = args.find {|a| a.class == Hash}
  io   = {} if io.nil?
  args.delete_if   {|a| a.class == Hash}
  # join input streams together if possible
  io[:input] = io[:input].join(' ') if io[:input].respond_to?(:join)
  return [io,opts]
end
readArray(iFile,varname) click to toggle source
# File lib/cdo_lib.rb, line 354
def Cdo.readArray(iFile,varname)
  filehandle = Cdo.readCdf(iFile)
  if filehandle.var_names.include?(varname)
    # return the data array
    filehandle.var(varname).get
  else
    raise ArgumentError, "Cannot find variable '#{varname}'"
  end
end
readCdf(iFile) click to toggle source
# File lib/cdo_lib.rb, line 344
def Cdo.readCdf(iFile)
  Cdo.loadCdf unless State[:returnCdf] 
  NetCDF.open(iFile)
end
readMaArray(iFile,varname) click to toggle source
# File lib/cdo_lib.rb, line 364
def Cdo.readMaArray(iFile,varname)
  filehandle = Cdo.readCdf(iFile)
  if filehandle.var_names.include?(varname)
    # return the data array
    filehandle.var(varname).get_with_miss
  else
    raise ArgumentError,"Cannot find variable '#{varname}'"
  end
end
returnCdf() click to toggle source
# File lib/cdo_lib.rb, line 254
def Cdo.returnCdf
  State[:returnCdf]
end
run(cmd,ofile='',options='',returnCdf=false,force=nil,returnArray=nil,returnMaArray=nil) click to toggle source
# File lib/cdo_lib.rb, line 125
def Cdo.run(cmd,ofile='',options='',returnCdf=false,force=nil,returnArray=nil,returnMaArray=nil)
  cmd = "#{@@CDO} -O #{options} #{cmd} "
  case ofile
  when $stdout
    retvals = Cdo.call(cmd)
    State[:logger].info(cmd+"\n") if State[:log]
    unless hasError(cmd,retvals)
      return retvals[:stdout].split($/).map {|l| l.chomp.strip}
    else
      raise ArgumentError,"CDO did NOT run successfully!"
    end
  else
    force = State[:forceOutput] if force.nil?
    if force or not File.exists?(ofile.to_s)
      ofile = MyTempfile.path if ofile.nil?
      cmd << "#{ofile}"
      retvals = call(cmd)
      State[:logger].info(cmd+"\n") if State[:log]
      if hasError(cmd,retvals)
        raise ArgumentError,"CDO did NOT run successfully!"
      end
    else
      warn "Use existing file '#{ofile}'" if Cdo.debug
    end
  end
  if not returnArray.nil?
    Cdo.readArray(ofile,returnArray)
  elsif not returnMaArray.nil?
    Cdo.readMaArray(ofile,returnMaArray)
  elsif returnCdf or State[:returnCdf]
    Cdo.readCdf(ofile)
  else
    return ofile
  end
end
setCdo(cdo) click to toggle source
# File lib/cdo_lib.rb, line 277
def Cdo.setCdo(cdo)
  puts "Will use #{cdo} instead of #@@CDO" if Cdo.debug
  @@CDO = cdo
  Cdo.getOperators(true)
  Cdo.getSupportedLibs(true)
end
setReturnCdf(value=true) click to toggle source
# File lib/cdo_lib.rb, line 243
def Cdo.setReturnCdf(value=true)
  if value
    Cdo.loadCdf
  end
  State[:returnCdf] = value
end
showlog() click to toggle source
# File lib/cdo_lib.rb, line 316
def Cdo.showlog
  @@file.rewind
  puts @@file.read
end
thicknessOfLevels(args) click to toggle source
# File lib/cdo_lib.rb, line 334
def Cdo.thicknessOfLevels(args)
  bound_levels = Cdo.boundaryLevels(args)
  delta_levels    = []
  bound_levels.each_with_index {|v,i| 
    next if 0 == i
    delta_levels << v - bound_levels[i-1]
  }
  delta_levels
end
unsetReturnCdf() click to toggle source
# File lib/cdo_lib.rb, line 250
def Cdo.unsetReturnCdf
  setReturnCdf(false)
end
version() click to toggle source
# File lib/cdo_lib.rb, line 235
def Cdo.version
  cmd     = @@CDO + ' 2>&1'
  help    = IO.popen(cmd).readlines.map {|l| l.chomp.lstrip}
  regexp  = %r{CDO version (\d.*), Copyright}
  line    = help.find {|v| v =~ regexp}
  version = regexp.match(line)[1]
end