require "numru/netcdf"
require "narray_miss"
module NumRu
class NetCDFVar
def get_with_miss(*args)
__interpret_missing_params if !defined?(@missval)
data = simple_get(*args)
if @vmin || @vmax
if @vmin
mask = (data >= @vmin)
mask = mask.and(data <= @vmax) if @vmax
else
mask = (data <= @vmax)
end
data = NArrayMiss.to_nam(data, mask)
elsif @missval # only missing_value is present.
mask = (data.ne(@missval))
data = NArrayMiss.to_nam(data, mask)
end
data
end
def get_with_miss_and_scaling(*args)
__interpret_missing_params if !defined?(@missval)
data = simple_get(*args)
data = unpack( data ) if !@miss_on_packed
if @vmin || @vmax
if @vmin
mask = (data >= @vmin)
mask = mask.and(data <= @vmax) if @vmax
else
mask = (data <= @vmax)
end
data = NArrayMiss.to_nam(data, mask)
elsif @missval # only missing_value is present.
mask = (data.ne(@missval))
data = NArrayMiss.to_nam(data, mask)
end
data = unpack( data ) if @miss_on_packed
data
end
def put_with_miss(data, *args)
if data.is_a?( NArrayMiss )
__interpret_missing_params if !defined?(@missval)
if @missval
simple_put(data.to_na(@missval), *args)
else
simple_put(data.to_na, *args)
end
else
simple_put(data, *args)
end
end
def put_with_miss_and_scaling(data, *args)
if data.is_a?( NArrayMiss )
__interpret_missing_params if !defined?(@missval)
if @missval
data = pack( data ) if @miss_on_packed
data = data.to_na(@missval)
data = pack( data ) if !@miss_on_packed
else
data = pack( data )
data = data.to_na
end
simple_put(data, *args)
else
scaled_put(data, *args)
end
end
######### private ##########
def __interpret_missing_params
# Interprets the specification of missing data,
# either by valid_range, (valid_min and/or valid_max), or missing_value.
# (unlike the User's guiede, missing_value is interpreted, but
# valid_* has a higher precedence.)
# Always sets @missval whether missing_value is defined or not,
# since it will be used as a fill value for data missing.
#
@vmin = att('valid_min')
@vmin = @vmin.get if @vmin # kept in a NArray(size==1) to consv type
@vmax = att('valid_max')
@vmax = @vmax.get if @vmax # kept in a NArray(size==1) to consv type
vrange = att('valid_range')
vrange = vrange.get if vrange
if vrange
vrange.sort!
@vmin = vrange[0..0] # kept in... (same)
@vmax = vrange[-1..-1] # kept in... (same)
end
@missval = att('missing_value')
if @missval
@missval = @missval.get # kept in... (same)
if @vmin && @vmax
if @vmin[0] <= @missval[0] && @missval[0] <= @vmax[0]
raise "missing_value #{@missval[0]} is in the valid range #{@vmin[0]}..#{@vmax[0]}"
end
else
if @vmin && @missval[0] >= @vmin[0]
raise "missing_value #{@missval[0]} >= valid min #{@vmin[0]}"
elsif @vmax && @missval[0] <= @vmax[0]
raise "missing_value #{@missval[0]} <= valid min #{@vmin[0]}"
end
end
else
if @vmin || @vmax
if (fill=att('_FillValue')) # equal, not ==
fill = fill.get
if @vmin && fill[0] < @vmin[0]
@missval = fill
end
if !@missval && @vmax && fill[0] > @vmax[0]
@missval = fill
end
end
if !@missval
if @vmin
if @vmin[0] >= 0
@missval = 0.99*@vmin - 1
else
@missval = 1.01*@vmin - 1
end
elsif @vmax
if @vmax[0] >= 0
@missval = 1.01*@vmax + 1
else
@missval = 0.99*@vmax + 1
end
end
end
end
end
if @vmin
miss_type = @vmin.typecode
elsif @vmax
miss_type = @vmax.typecode
elsif @missval
miss_type = @missval.typecode
else
miss_type = nil
end
sf = att('scale_factor')
ao = att('add_offset')
if ( miss_type && ( sf || ao ) )
sfao_type = ( sf ? sf.typecode : ao.typecode )
if ( miss_type != self.typecode ) && ( miss_type == sfao_type )
@miss_on_packed = false # rather exceptional (GDT)
else
@miss_on_packed = true # for most conventions such as CF
end
else
@miss_on_packed = true # though no need to determine in this case
end
end
private :__interpret_missing_params
end
end
if $0 == __FILE__
include NumRu
filename = "tmp.nc"
print "creating ",filename,"...\n"
file=NetCDF.create(filename)
nx = 10
dimx = file.def_dim("x",nx)
xf = file.def_var("xf","sfloat",[dimx])
xfn = file.def_var("xfn","sfloat",[dimx])
xf.put_att("valid_range",[-1e12,1e12])
f = 10 ** (2*NArray.sfloat(nx).indgen!)
xr = file.def_var("xr","sint",[dimx])
xr.put_att("valid_max",[0.5])
xr.put_att("scale_factor",1e-4)
xr.put_att("add_offset",0.5)
xr2 = file.def_var("xr2","sint",[dimx])
xr2.put_att("valid_max",NArray.sint(1).fill!(1000))
xr2.put_att("scale_factor",1e-4)
xr2.put_att("add_offset",0.5)
r = NArray.sfloat(nx).random!
file.enddef
xf.put(f)
xfn.put(f)
xr.scaled_put(r)
file.close
file = NetCDF.open(filename,'r+')
xf = file.var('xf')
xfn = file.var('xfn')
p "f0"
xf.get.each{|v| print "#{v} "} ; print "\n"
p( 'f1', nam = xf.get_with_miss )
def xf.get(*args); get_with_miss(*args); end
p( 'f12', xf[2..-3].to_na )
p( 'fn10', xfn.get_with_miss )
p( 'fn11', xfn.get_with_miss_and_scaling )
nam.invalidation([0,1])
p 'f2', nam
xf.put_with_miss(nam)
p( 'f3', xf.get_with_miss )
xr = file.var('xr')
p "r0"
xr.simple_get.each{|v| print "#{v} "} ; print "\n"
p( 'r1', xr.get_with_miss_and_scaling )
def xr.get(*args); get_with_miss_and_scaling(*args); end
def xr.put(*args); put_with_miss_and_scaling(*args); end
xr[0..3] = xr[0..3]*10
p( 'r2', xr.get_with_miss_and_scaling )
p 'r',r
xr2.put_with_miss_and_scaling(r)
p 'xr2',xr2.get_with_miss_and_scaling
file.close
print "** ncdump tmp.nc **\n", `ncdump tmp.nc`
end
syntax highlighted by Code2HTML, v. 0.9.1