Class: Cdo
- Inherits:
-
Object
- Object
- Cdo
- Defined in:
- lib/cdo.rb
Overview
Copyright 2011-2019 Ralf Mueller, [email protected]
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Constant Summary collapse
- NoOutputOperators =
hardcoded fallback list of output operators - from 1.8.0 there is an options for this: –operators_no_output this list works for cdo-1.6.4
%w[cdiread cmor codetab conv_cmor_table diff diffc diffn diffp diffv dump_cmor_table dumpmap filedes gmtcells gmtxyz gradsdes griddes griddes2 gridverify info infoc infon infop infos infov map 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 showattribute showatts showattsglob showattsvar showcode showdate showformat showgrid showlevel showltype showmon showname showparam showstdname showtime showtimestamp showunit showvar showyear sinfo sinfoc sinfon sinfop sinfov spartab specinfo tinfo vardes vct vct2 verifygrid vlist xinfon zaxisdes]
- TwoOutputOperators =
%w[trend samplegridicon mrotuv eoftime eofspatial eof3dtime eof3dspatial eof3d eof complextorect complextopol]
- MoreOutputOperators =
%w[distgrid eofcoeff eofcoeff3d intyear scatter splitcode splitday splitgrid splithour splitlevel splitmon splitname splitparam splitrec splitseas splitsel splittabnum splitvar splityear splityearmon splitzaxis]
Instance Attribute Summary collapse
-
#cdo ⇒ Object
Returns the value of attribute cdo.
-
#debug ⇒ Object
Returns the value of attribute debug.
-
#env ⇒ Object
Returns the value of attribute env.
-
#filetypes ⇒ Object
readonly
Returns the value of attribute filetypes.
-
#forceOutput ⇒ Object
Returns the value of attribute forceOutput.
-
#hasNetcdf ⇒ Object
readonly
Returns the value of attribute hasNetcdf.
-
#logFile ⇒ Object
Returns the value of attribute logFile.
-
#logging ⇒ Object
Returns the value of attribute logging.
-
#operators ⇒ Object
readonly
Returns the value of attribute operators.
-
#returnCdf ⇒ Object
Returns the value of attribute returnCdf.
Instance Method Summary collapse
-
#boundaryLevels(args) ⇒ Object
compute vertical boundary levels from full levels.
-
#check ⇒ Object
check if cdo backend is working.
-
#cleanTempDir ⇒ Object
remove tempfiles created from this or previous runs.
-
#collectLogs ⇒ Object
collect logging messages.
-
#hasCdo(path = @cdo) ⇒ Object
check if the CDO binary is present and works.
-
#help(operator = nil) ⇒ Object
show Cdo’s built-in help for given operator.
-
#initialize(cdo: 'cdo', returnFalseOnError: false, returnNilOnError: false, forceOutput: true, env: {}, debug: false, tempdir: Dir.tmpdir, logging: false, logFile: StringIO.new) ⇒ Cdo
constructor
A new instance of Cdo.
-
#openCdf(iFile) ⇒ Object
return cdf handle opened in append more.
-
#readArray(iFile, varname) ⇒ Object
return narray for given variable name.
-
#readCdf(iFile, mode = 'r') ⇒ Object
return cdf handle to given file readonly.
-
#readMaArray(iFile, varname) ⇒ Object
return a masked array for given variable name.
-
#showLog ⇒ Object
print the loggin messaged.
-
#thicknessOfLevels(args) ⇒ Object
compute level thicknesses from given full levels.
-
#version(verbose = false) ⇒ Object
return CDO version string.
Constructor Details
#initialize(cdo: 'cdo', returnFalseOnError: false, returnNilOnError: false, forceOutput: true, env: {}, debug: false, tempdir: Dir.tmpdir, logging: false, logFile: StringIO.new) ⇒ Cdo
Returns a new instance of Cdo.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/cdo.rb', line 65 def initialize(cdo: 'cdo', returnFalseOnError: false, returnNilOnError: false, forceOutput: true, env: {}, debug: false, tempdir: Dir.tmpdir, logging: false, logFile: StringIO.new) # setup path to cdo executable @cdo = ENV.has_key?('CDO') ? ENV['CDO'] : cdo @operators = getOperators(@cdo) @noOutputOperators = @operators.select {|op,io| 0 == io}.keys @hasNetcdf = loadOptionalLibs @forceOutput = forceOutput @env = env @debug = ENV.has_key?('DEBUG') ? true : debug @returnNilOnError = returnNilOnError @returnFalseOnError = returnFalseOnError @tempStore = CdoTempfileStore.new(tempdir) @logging = logging @logFile = logFile @logger = Logger.new(@logFile,'daily') @logger.level = Logger::INFO @config = getFeatures # create methods to descibe what can be done with the binary @config.each {|k,v| self.class.send :define_method, k.tr('-','_') do v end } # ignore return code 1 for diff operators (from 1.9.6 onwards) @exit_success = lambda {|operatorName| return 0 if version < '1.9.6' return 0 if 'diff' != operatorName[0,4] return 1 } 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))
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/cdo.rb', line 358 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
#cdo ⇒ Object
Returns the value of attribute cdo.
62 63 64 |
# File 'lib/cdo.rb', line 62 def cdo @cdo end |
#debug ⇒ Object
Returns the value of attribute debug.
62 63 64 |
# File 'lib/cdo.rb', line 62 def debug @debug end |
#env ⇒ Object
Returns the value of attribute env.
62 63 64 |
# File 'lib/cdo.rb', line 62 def env @env end |
#filetypes ⇒ Object (readonly)
Returns the value of attribute filetypes.
63 64 65 |
# File 'lib/cdo.rb', line 63 def filetypes @filetypes end |
#forceOutput ⇒ Object
Returns the value of attribute forceOutput.
62 63 64 |
# File 'lib/cdo.rb', line 62 def forceOutput @forceOutput end |
#hasNetcdf ⇒ Object (readonly)
Returns the value of attribute hasNetcdf.
63 64 65 |
# File 'lib/cdo.rb', line 63 def hasNetcdf @hasNetcdf end |
#logFile ⇒ Object
Returns the value of attribute logFile.
62 63 64 |
# File 'lib/cdo.rb', line 62 def logFile @logFile end |
#logging ⇒ Object
Returns the value of attribute logging.
62 63 64 |
# File 'lib/cdo.rb', line 62 def logging @logging end |
#operators ⇒ Object (readonly)
Returns the value of attribute operators.
63 64 65 |
# File 'lib/cdo.rb', line 63 def operators @operators end |
#returnCdf ⇒ Object
Returns the value of attribute returnCdf.
62 63 64 |
# File 'lib/cdo.rb', line 62 def returnCdf @returnCdf end |
Instance Method Details
#boundaryLevels(args) ⇒ Object
compute vertical boundary levels from full levels
489 490 491 492 493 494 495 496 497 |
# File 'lib/cdo.rb', line 489 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 |
#check ⇒ Object
check if cdo backend is working
425 426 427 428 429 430 431 432 |
# File 'lib/cdo.rb', line 425 def check return false unless hasCdo retval = _call("#{@cdo} -V") pp retval if @debug return true end |
#cleanTempDir ⇒ Object
remove tempfiles created from this or previous runs
481 482 483 |
# File 'lib/cdo.rb', line 481 def cleanTempDir @tempStore.cleanTempDir end |
#collectLogs ⇒ Object
collect logging messages
402 403 404 405 406 407 408 409 |
# File 'lib/cdo.rb', line 402 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
check if the CDO binary is present and works
417 418 419 420 421 422 |
# File 'lib/cdo.rb', line 417 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
392 393 394 395 396 397 398 399 |
# File 'lib/cdo.rb', line 392 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 |
#openCdf(iFile) ⇒ Object
return cdf handle opened in append more
454 455 456 |
# File 'lib/cdo.rb', line 454 def openCdf(iFile) readCdf(iFile,'r+') end |
#readArray(iFile, varname) ⇒ Object
return narray for given variable name
459 460 461 462 463 464 465 466 467 |
# File 'lib/cdo.rb', line 459 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, mode = 'r') ⇒ Object
return cdf handle to given file readonly
445 446 447 448 449 450 451 |
# File 'lib/cdo.rb', line 445 def readCdf(iFile,mode='r') if @hasNetcdf then NumRu::NetCDF.open(iFile,mode) else raise LoadError,"Could not load ruby-netcdf" end end |
#readMaArray(iFile, varname) ⇒ Object
return a masked array for given variable name
470 471 472 473 474 475 476 477 478 |
# File 'lib/cdo.rb', line 470 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 |
#showLog ⇒ Object
print the loggin messaged
412 413 414 |
# File 'lib/cdo.rb', line 412 def showLog puts collectLogs end |
#thicknessOfLevels(args) ⇒ Object
compute level thicknesses from given full levels
500 501 502 503 504 505 506 507 508 |
# File 'lib/cdo.rb', line 500 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
return CDO version string
435 436 437 438 439 440 441 442 |
# File 'lib/cdo.rb', line 435 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 |