Class: Cdo

Inherits:
Object
  • Object
show all
Defined in:
lib/cdo.rb

Constant Summary collapse

NoOutputOperators =

hardcoded fallback list of output operators - from 1.8.0 there is an options for this: –operators_no_output

%w[cdiread cmor codetab conv_cmor_table diff diffc diffn diffp
diffv dump_cmor_table dumpmap filedes ggstat ggstats gmtcells gmtxyz gradsdes
griddes griddes2 gridverify info infoc infon infop infos infov map ncode
ncode ndate ngridpoints ngrids nlevel nmon npar ntime nvar nyear output
outputarr outputbounds outputboundscpt outputcenter outputcenter2
outputcentercpt outputext outputf outputfld outputint outputkey outputsrv
outputtab outputtri outputts outputvector outputvrml outputxyz pardes partab
partab2 seinfo seinfoc seinfon seinfop showcode showdate showformat showlevel
showltype showmon showname showparam showstdname showtime showtimestamp
showunit showvar showyear sinfo sinfoc sinfon sinfop sinfov
spartab specinfo tinfo vardes vct vct2 verifygrid vlist zaxisdes]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cdo: 'cdo', returnCdf: false, returnFalseOnError: false, forceOutput: true, env: {}, logging: false, logFile: StringIO.new, debug: false, returnNilOnError: false) ⇒ Cdo

Returns a new instance of Cdo.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/cdo.rb', line 30

def initialize(cdo: 'cdo',
               returnCdf: false,
               returnFalseOnError: false,
               forceOutput: true,
               env: {},
               logging: false,
               logFile: StringIO.new,
               debug: false,
               returnNilOnError: false)

  # setup path to cdo executable
  @cdo = ENV.has_key?('CDO') ? ENV['CDO'] : cdo

  @operators              = getOperators(@cdo)
  @returnCdf              = returnCdf
  @forceOutput            = forceOutput
  @env                    = env
  @debug                  = ENV.has_key?('DEBUG') ? true : debug
  @noOutputOperators      = getNoOuputOperators(@cdo) # operators without output files (write to stdout)
  @returnNilOnError       = returnNilOnError

  @filetypes              = getFiletypes
  @returnFalseOnError     = returnFalseOnError

  @logging                = logging
  @logFile                = logFile
  @logger                 = Logger.new(@logFile,'a')
  @logger.level           = Logger::INFO
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object (private)

Implementation of operator calls using ruby’s meta programming skills

args is expected to look like

[opt1,...,optN,:input => iStream,:output => oStream, :options => ' ']
where iStream could be another CDO call (timmax(selname(Temp,U,V,ifile.nc))


247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/cdo.rb', line 247

def method_missing(sym, *args, &block)
  operatorName = sym.to_s
  puts "Operator #{operatorName} is called" if @debug

  # exit eary on missing operator
  unless @operators.include?(operatorName)
    return false if @returnFalseOnError
    raise ArgumentError,"Operator #{operatorName} not found"
  end

  io, operatorParameters = Cdo.parseArgs(args)

  # mark calls for operators without output files
  io[:output] = $stdout if @noOutputOperators.include?(operatorName)

  _run(operatorName,operatorParameters,io)
end

Instance Attribute Details

#cdoObject

Returns the value of attribute cdo.



27
28
29
# File 'lib/cdo.rb', line 27

def cdo
  @cdo
end

#debugObject

Returns the value of attribute debug.



27
28
29
# File 'lib/cdo.rb', line 27

def debug
  @debug
end

#envObject

Returns the value of attribute env.



27
28
29
# File 'lib/cdo.rb', line 27

def env
  @env
end

#filetypesObject (readonly)

Returns the value of attribute filetypes.



28
29
30
# File 'lib/cdo.rb', line 28

def filetypes
  @filetypes
end

#forceOutputObject

Returns the value of attribute forceOutput.



27
28
29
# File 'lib/cdo.rb', line 27

def forceOutput
  @forceOutput
end

#logFileObject

Returns the value of attribute logFile.



27
28
29
# File 'lib/cdo.rb', line 27

def logFile
  @logFile
end

#loggingObject

Returns the value of attribute logging.



27
28
29
# File 'lib/cdo.rb', line 27

def logging
  @logging
end

#operatorsObject (readonly)

Returns the value of attribute operators.



28
29
30
# File 'lib/cdo.rb', line 28

def operators
  @operators
end

#returnCdfObject

Returns the value of attribute returnCdf.



27
28
29
# File 'lib/cdo.rb', line 27

def returnCdf
  @returnCdf
end

Instance Method Details

#boundaryLevels(args) ⇒ Object

compute vertical boundary levels from full levels



370
371
372
373
374
375
376
377
378
# File 'lib/cdo.rb', line 370

def boundaryLevels(args)
  ilevels         = self.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

#checkObject

check if cdo backend is working



310
311
312
313
314
315
316
317
# File 'lib/cdo.rb', line 310

def check
  return false unless hasCdo

  retval = _call("#{@cdo} -V")
  pp retval if @debug

  return true
end

#collectLogsObject

collect logging messages



290
291
292
293
294
295
296
297
# File 'lib/cdo.rb', line 290

def collectLogs
  if @logger.instance_variable_get(:'@logdev').filename.nil?
    @logFile.rewind
    return @logFile.read
  else
    return File.open(@logFile).readlines
  end
end

#hasCdo(path = @cdo) ⇒ Object



303
304
305
306
307
308
# File 'lib/cdo.rb', line 303

def hasCdo(path=@cdo)
  executable = system("#{path} -V >/dev/null 2>&1")
  fullpath   = File.exists?(path) and File.executable?(path)

  return (executable or fullpath)
end

#help(operator = nil) ⇒ Object

show Cdo’s built-in help for given operator



280
281
282
283
284
285
286
287
# File 'lib/cdo.rb', line 280

def help(operator=nil)
  if operator.nil?
    puts _call([@cdo,'-h'].join(' '))[:stderr]
  else
    operator = operator.to_s
    puts _call([@cdo,'-h',operator].join(' ')).values_at(:stdout,:stderr)
  end
end

#noOutputOpsObject



362
363
364
# File 'lib/cdo.rb', line 362

def noOutputOps
  getNoOuputOperators(@cdo)
end

#openCdf(iFile) ⇒ Object

return cdf handle opened in append more



335
336
337
338
# File 'lib/cdo.rb', line 335

def openCdf(iFile)
  loadCdf
  NumRu::NetCDF.open(iFile,'r+')
end

#readArray(iFile, varname) ⇒ Object

return narray for given variable name



341
342
343
344
345
346
347
348
349
# File 'lib/cdo.rb', line 341

def readArray(iFile,varname)
  filehandle = 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) ⇒ Object

return cdf handle to given file readonly



329
330
331
332
# File 'lib/cdo.rb', line 329

def readCdf(iFile)
  loadCdf
  NumRu::NetCDF.open(iFile)
end

#readMaArray(iFile, varname) ⇒ Object

return a masked array for given variable name



352
353
354
355
356
357
358
359
360
# File 'lib/cdo.rb', line 352

def readMaArray(iFile,varname)
  filehandle = 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

#showLogObject

print the loggin messaged



299
300
301
# File 'lib/cdo.rb', line 299

def showLog
  puts collectLogs
end

#thicknessOfLevels(args) ⇒ Object

compute level thicknesses from given full levels



381
382
383
384
385
386
387
388
389
# File 'lib/cdo.rb', line 381

def thicknessOfLevels(args)
  bound_levels = self.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

#version(verbose = false) ⇒ Object



319
320
321
322
323
324
325
326
# File 'lib/cdo.rb', line 319

def version(verbose=false)
  info = IO.popen("#{@cdo} -V 2>&1").readlines
  if verbose then
    return info.join
  else
    return info.first.split(/version/i).last.strip.split(' ').first
  end
end