gentooboontoo-gphys 0.6.1.3 → 1.3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +5631 -464
- data/LICENSE.txt +34 -0
- data/README +23 -25
- data/bin/gdir_client +25 -7
- data/bin/gdir_server +19 -13
- data/bin/gpaop +41 -28
- data/bin/gpcat +19 -11
- data/bin/gpcut +20 -11
- data/bin/gpedit +37 -1
- data/bin/gplist +5 -4
- data/bin/gpmath +21 -14
- data/bin/gpmaxmin +9 -7
- data/bin/gpprint +15 -11
- data/bin/gpvect +217 -96
- data/bin/gpview +278 -123
- data/bin/grads2nc_with_gphys +11 -6
- data/doc/attribute.html +1 -1
- data/doc/axis.html +85 -66
- data/doc/coordmapping.html +22 -22
- data/doc/dclext.html +709 -0
- data/doc/derivative/gphys-derivative.html +33 -13
- data/doc/derivative/numru-derivative.html +60 -31
- data/doc/gdir.html +76 -76
- data/doc/gdir_server.html +28 -16
- data/doc/ggraph.html +493 -706
- data/doc/gpcat.html +28 -11
- data/doc/gpcut.html +26 -11
- data/doc/gphys.html +195 -71
- data/doc/gphys_fft.html +162 -21
- data/doc/gphys_grads_io.html +9 -9
- data/doc/gphys_grib_io.html +7 -7
- data/doc/gphys_io.html +118 -31
- data/doc/gphys_io_common.html +1 -1
- data/doc/gphys_netcdf_io.html +14 -14
- data/doc/gplist.html +6 -5
- data/doc/gpmath.html +32 -14
- data/doc/gpmaxmin.html +9 -7
- data/doc/gpprint.html +14 -11
- data/doc/gpview.html +254 -146
- data/doc/grads2nc_with_gphys.html +6 -8
- data/doc/grads_gridded.html +77 -77
- data/doc/grib.html +102 -59
- data/doc/grid.html +45 -61
- data/doc/index.html +51 -41
- data/doc/index.rd +47 -36
- data/doc/netcdf_convention.html +39 -39
- data/doc/unumeric.html +79 -30
- data/doc/update +2 -1
- data/doc/varray.html +62 -56
- data/doc/varraycomposite.html +3 -3
- data/ext/ext_coord.c +209 -0
- data/ext/ext_init.c +7 -0
- data/ext/extconf.rb +41 -0
- data/ext/interpo.c +536 -0
- data/ext/multibitIO.c +567 -0
- data/lib/numru/dcl_mouse.rb +71 -0
- data/lib/numru/dclext.rb +2749 -0
- data/lib/numru/derivative.rb +124 -31
- data/lib/numru/ganalysis.rb +7 -0
- data/lib/numru/ganalysis/covariance.rb +154 -0
- data/lib/numru/ganalysis/eof.rb +302 -0
- data/lib/numru/ganalysis/histogram.rb +337 -0
- data/lib/numru/ganalysis/met.rb +872 -0
- data/lib/numru/ganalysis/planet.rb +392 -0
- data/lib/numru/ggraph.rb +1709 -2498
- data/lib/numru/gphys.rb +7 -1
- data/lib/numru/gphys/assoccoords.rb +384 -0
- data/lib/numru/gphys/attribute.rb +10 -11
- data/lib/numru/gphys/axis.rb +97 -25
- data/lib/numru/gphys/coordmapping.rb +2 -2
- data/lib/numru/gphys/derivative.rb +117 -46
- data/lib/numru/gphys/gphys.rb +595 -31
- data/lib/numru/gphys/gphys_fft.rb +365 -13
- data/lib/numru/gphys/gphys_grads_io.rb +6 -5
- data/lib/numru/gphys/gphys_grib_io.rb +6 -6
- data/lib/numru/gphys/gphys_gtool3_io.rb +162 -0
- data/lib/numru/gphys/gphys_hdfeos5_io.rb +672 -0
- data/lib/numru/gphys/gphys_io.rb +260 -20
- data/lib/numru/gphys/gphys_io_common.rb +1 -1
- data/lib/numru/gphys/gphys_netcdf_io.rb +111 -40
- data/lib/numru/gphys/gphys_nusdas_io.rb +64 -7
- data/lib/numru/gphys/grads_gridded.rb +158 -57
- data/lib/numru/gphys/grib.rb +205 -157
- data/lib/numru/gphys/grib_params.rb +196 -1
- data/lib/numru/gphys/grid.rb +214 -83
- data/lib/numru/gphys/gtool3.rb +771 -0
- data/lib/numru/gphys/interpolate.rb +992 -0
- data/lib/numru/gphys/mdstorage.rb +145 -0
- data/lib/numru/gphys/narray_ext.rb +34 -0
- data/lib/numru/gphys/netcdf_convention.rb +44 -2
- data/lib/numru/gphys/subsetmapping.rb +1 -1
- data/lib/numru/gphys/unumeric.rb +101 -8
- data/lib/numru/gphys/varray.rb +66 -20
- data/lib/numru/gphys/varraycomposite.rb +107 -29
- data/lib/numru/gphys/varraygrib.rb +70 -8
- data/lib/numru/gphys/varraygtool3.rb +226 -0
- data/lib/numru/gphys/varrayhdfeos5.rb +451 -0
- data/lib/numru/gphys/varraynetcdf.rb +13 -5
- data/lib/numru/gphys/version.rb +3 -0
- data/sample/druby_cli1.rb +2 -0
- data/sample/druby_cli2.rb +0 -6
- data/sample/druby_serv2.rb +0 -13
- data/sample/ncep_theta_coord.rb +79 -0
- data/test/eof_slp.rb +28 -0
- data/test/mltbit.dat +0 -0
- data/test/test_multibitIO.rb +19 -0
- data/testdata/assoc_crds.nc +0 -0
- metadata +79 -8
- data/lib/numru/dclext_datetime_ax.rb +0 -220
- data/lib/numru/vizshot.rb +0 -697
@@ -0,0 +1,145 @@
|
|
1
|
+
require "narray"
|
2
|
+
|
3
|
+
module NumRu
|
4
|
+
class MDStorage
|
5
|
+
def initialize(rank=1)
|
6
|
+
raise(ArgumentError,"rank must be a positive integer") if !(rank>0)
|
7
|
+
@rank = rank
|
8
|
+
@shape = []
|
9
|
+
rank.times{@shape.push(1)}
|
10
|
+
@data = [nil]
|
11
|
+
(rank-1).times{
|
12
|
+
@data = [@data]
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :rank
|
17
|
+
|
18
|
+
def shape
|
19
|
+
@shape.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
# add a new dimension to the last
|
23
|
+
def add_dim
|
24
|
+
@rank += 1
|
25
|
+
@shape.push(1)
|
26
|
+
@data = [@data]
|
27
|
+
end
|
28
|
+
|
29
|
+
# increase the length of a dimension by one
|
30
|
+
def extend(dim)
|
31
|
+
if dim<0 or dim>=rank
|
32
|
+
raise(ArgumentError,"invalid dim (#{dim}): not in #{0..rank-1}")
|
33
|
+
end
|
34
|
+
yield_at_depth(@data,rank-1-dim){|a|
|
35
|
+
a.push( dim==0 ? nil : make_nested_array(shape[0..dim-1]) )
|
36
|
+
}
|
37
|
+
@shape[dim] += 1
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
# substituion at a position specified with integers (only one element)
|
42
|
+
def []=(*args)
|
43
|
+
val = args.pop
|
44
|
+
raise(ArgumentError,"# of args != rank (#{rank})") if args.length != rank
|
45
|
+
x = @data
|
46
|
+
(rank-1).downto(1) do |d|
|
47
|
+
idx = args[d]
|
48
|
+
raise(ArgumentError,"all args must be integers") if !idx.is_a?(Integer)
|
49
|
+
len = shape[d]
|
50
|
+
idx += len if idx<0
|
51
|
+
raise("Too big negative index for dim #{d}: #{idx-len}") if idx<0
|
52
|
+
if 0<=idx and idx<len
|
53
|
+
x = x[idx]
|
54
|
+
elsif idx >= len
|
55
|
+
(idx-len+1).times{extend(d)}
|
56
|
+
x = x[idx]
|
57
|
+
else
|
58
|
+
raise(ArgumentError,"invalid specification")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
idx = args[0]
|
63
|
+
len = shape[0]
|
64
|
+
idx += len if idx<0
|
65
|
+
raise("Too big negative index for dim #{0}: #{idx-len}") if idx<0
|
66
|
+
if idx >= len
|
67
|
+
(idx-len+1).times{extend(0)}
|
68
|
+
end
|
69
|
+
x[idx] = val
|
70
|
+
end
|
71
|
+
|
72
|
+
# read from a position specified with integers (only one element)
|
73
|
+
def [](*args)
|
74
|
+
raise(ArgumentError,"# of args != rank (#{rank})") if args.length != rank
|
75
|
+
x = @data
|
76
|
+
args.reverse_each do |idx|
|
77
|
+
raise(ArgumentError,"all args must be integers") if !idx.is_a?(Integer)
|
78
|
+
x = x[idx]
|
79
|
+
return(x) if x.nil?
|
80
|
+
end
|
81
|
+
x
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_na
|
85
|
+
NArray.to_na(@data)
|
86
|
+
end
|
87
|
+
|
88
|
+
#############################################
|
89
|
+
## < private methods >
|
90
|
+
private
|
91
|
+
=begin
|
92
|
+
def __rubber_expansion( args )
|
93
|
+
if (id = args.index(false)) # substitution into id
|
94
|
+
# false is incuded
|
95
|
+
alen = args.length
|
96
|
+
if args.rindex(false) != id
|
97
|
+
raise ArguemntError,"only one rubber dimension is permitted"
|
98
|
+
elsif alen > rank+1
|
99
|
+
raise ArgumentError, "too many args"
|
100
|
+
end
|
101
|
+
ar = ( id!=0 ? args[0..id-1] : [] )
|
102
|
+
args = ar + [true]*(rank-alen+1) + args[id+1..-1]
|
103
|
+
end
|
104
|
+
args
|
105
|
+
end
|
106
|
+
=end
|
107
|
+
|
108
|
+
# make a neste multi-D Array filled with nil
|
109
|
+
def make_nested_array(shape)
|
110
|
+
if shape.length == 1
|
111
|
+
Array.new(shape[0]) # => [nil,nil,...,nil]
|
112
|
+
elsif shape.length > 1 # recursive construction
|
113
|
+
(0...shape[-1]).collect{make_nested_array(shape[0..-2])}
|
114
|
+
else
|
115
|
+
raise ArgumentError, "shape must have 1 or more elements"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# call the block at the depth in the nested array
|
120
|
+
def yield_at_depth(ary,depth, &blk)
|
121
|
+
if depth==0
|
122
|
+
blk.call(ary) # call the block
|
123
|
+
elsif depth>0
|
124
|
+
ary.each{|sub| yield_at_depth(sub,depth-1,&blk)}
|
125
|
+
else
|
126
|
+
raise ArgumentError, "depth must be >= 0"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
if $0 == __FILE__
|
133
|
+
include NumRu
|
134
|
+
a = MDStorage.new(3)
|
135
|
+
p a
|
136
|
+
p a.extend(2)
|
137
|
+
p a.extend(2)
|
138
|
+
p a.extend(0)
|
139
|
+
a[0,0,0] = 10.9
|
140
|
+
a[1,0,-1] = "XX"
|
141
|
+
p a, a[0,0,0], a[1,0,-1]
|
142
|
+
a[2,0,2] = '###'
|
143
|
+
p a
|
144
|
+
p a.to_na
|
145
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "narray"
|
2
|
+
|
3
|
+
class NArray
|
4
|
+
|
5
|
+
@@dump_size_limit = -1 # max len to allow dump / no limit if negative
|
6
|
+
def self.dump_size_limit=(lmt)
|
7
|
+
@@dump_size_limit = lmt
|
8
|
+
end
|
9
|
+
def self.dump_size_limit
|
10
|
+
@@dump_size_limit
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.endian
|
14
|
+
NArray[1].to_s[1] == 1 ? :little : :big
|
15
|
+
end
|
16
|
+
|
17
|
+
def _dump(limit)
|
18
|
+
if (@@dump_size_limit <= 0) || (size <= @@dump_size_limit)
|
19
|
+
Marshal.dump([typecode, shape, NArray.endian, to_s])
|
20
|
+
else
|
21
|
+
raise "size of the NArray (#{size}) is too large to dump "+
|
22
|
+
"(limit: #{DUMP_SIZE_LIMIT})"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self._load(str)
|
27
|
+
ary = Marshal.load(str)
|
28
|
+
typecode, shape, endian, str = ary
|
29
|
+
na = NArray.to_na(str, typecode, *shape)
|
30
|
+
na = na.swap_byte unless endian == NArray.endian
|
31
|
+
return na
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -167,7 +167,8 @@ module NumRu
|
|
167
167
|
when /^Wind Profiler/
|
168
168
|
NetCDF_Convention_Wind_Profiler
|
169
169
|
else
|
170
|
-
NetCDF_Convention_Users_Guide
|
170
|
+
#NetCDF_Convention_Users_Guide
|
171
|
+
NetCDF_Convention_CF
|
171
172
|
end
|
172
173
|
end
|
173
174
|
end
|
@@ -299,8 +300,49 @@ module NumRu
|
|
299
300
|
nil # no rule for that
|
300
301
|
end
|
301
302
|
|
303
|
+
def assoc_coord_names(data)
|
304
|
+
nil # no rule for that
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
module NetCDF_Convention_CF
|
310
|
+
# http://cf-pcmdi.llnl.gov/
|
311
|
+
|
312
|
+
# < inherit the Users guide convention >
|
313
|
+
|
314
|
+
module Attribute_Mixin
|
315
|
+
include NetCDF_Convention_Users_Guide::Attribute_Mixin
|
316
|
+
end # module Attribute_Mixin
|
317
|
+
module VArray_Mixin
|
318
|
+
include NetCDF_Convention_Users_Guide::VArray_Mixin
|
319
|
+
end # module VArray_Mixin
|
320
|
+
module_function
|
321
|
+
extend NetCDF_Convention_Users_Guide
|
322
|
+
public_class_method :aux_var_names, :coord_var_names, :cell_bounds?, :cell_center?
|
323
|
+
|
324
|
+
########### original part starts here #################
|
325
|
+
|
326
|
+
def assoc_coord_names(data)
|
327
|
+
if s = data.get_att("coordinates")
|
328
|
+
nms = s.split(/ +/)
|
329
|
+
case data.file
|
330
|
+
when NArray
|
331
|
+
fl = data.file[0]
|
332
|
+
else
|
333
|
+
fl = data.file
|
334
|
+
end
|
335
|
+
nms.delete_if{|nm| !fl.var(nm)}
|
336
|
+
nms.delete_if{|nm| fl.dim_names.include?(nm)}
|
337
|
+
nms
|
338
|
+
else
|
339
|
+
nil
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
302
343
|
end
|
303
344
|
|
345
|
+
|
304
346
|
module NetCDF_Convention_Wind_Profiler
|
305
347
|
# Wind Profiler Convention
|
306
348
|
# http://www.kurasc.kyoto-u.ac.jp/radar-group/wind_profiler_conventions/
|
@@ -316,7 +358,7 @@ module NumRu
|
|
316
358
|
########################
|
317
359
|
module_function
|
318
360
|
extend NetCDF_Convention_Users_Guide
|
319
|
-
public_class_method :cell_bounds?, :cell_center
|
361
|
+
public_class_method :cell_bounds?, :cell_center?, :assoc_coord_names
|
320
362
|
|
321
363
|
def to_s
|
322
364
|
"Wind Profiler (http://www.kurasc.kyoto-u.ac.jp/radar-group/wind_profiler_conventions/)"
|
@@ -231,7 +231,7 @@ module NumRu
|
|
231
231
|
idxary = @index_array[mida]
|
232
232
|
if idxary.length==1
|
233
233
|
fst = idxary[0]
|
234
|
-
len =
|
234
|
+
len = stp = 1
|
235
235
|
slicer = __make_regular_slicer((scl=mapping.collapsed),fst,len,stp)
|
236
236
|
SubsetMapping1D.new0.initialize_regular(slicer,scl,fst,len,stp)
|
237
237
|
else
|
data/lib/numru/gphys/unumeric.rb
CHANGED
@@ -187,29 +187,88 @@ module NumRu
|
|
187
187
|
new(val, uni)
|
188
188
|
end
|
189
189
|
|
190
|
+
@@supported_calendars = [nil,"gregorian", "standard", "proleptic_gregorian",
|
191
|
+
"noleap", "365_day", "360_day"]
|
192
|
+
|
193
|
+
def self::supported_calendar?(cal)
|
194
|
+
@@supported_calendars.include?(cal)
|
195
|
+
end
|
196
|
+
|
197
|
+
def self::supported_calendars
|
198
|
+
@@supported_calendars.dup
|
199
|
+
end
|
200
|
+
|
190
201
|
# * date (Date or DateTime)
|
191
202
|
# * units (Units or String) : units of the UNumeric to be created
|
192
|
-
def self::from_date(date, units)
|
203
|
+
def self::from_date(date, units, calendar=nil)
|
193
204
|
sunits = units.to_s
|
194
205
|
/(.*) *since *(.*)/ =~ sunits
|
195
206
|
if (!$1 or !$2)
|
196
207
|
raise("Units mismatch. Requires time units that includes 'since'")
|
197
208
|
end
|
198
209
|
tun = Units[$1]
|
199
|
-
since = DateTime.parse($2)
|
210
|
+
since = DateTime.parse(UNumeric::before_date_parse($2))
|
200
211
|
if( tun =~ Units['months since 0001-01-01'] )
|
201
212
|
year0,mon0 = since.year,since.mon
|
202
213
|
year,mon = date.year,date.mon
|
203
214
|
time = Units['months'].convert((year*12+mon)-(year0*12+mon0), tun)
|
204
215
|
elsif( tun =~ Units['days since 0001-01-01'] )
|
205
|
-
|
216
|
+
case calendar
|
217
|
+
when nil, "gregorian", "standard"
|
218
|
+
time = Units['days'].convert( date-since, tun )
|
219
|
+
when "proleptic_gregorian"
|
220
|
+
since = DateTime.parse(UNumeric::before_date_parse($2),false,Date::GREGORIAN)
|
221
|
+
time = Units['days'].convert( date-since, tun )
|
222
|
+
when "noleap", "365_day"
|
223
|
+
since_yday = since - DateTime.new(since.year,1,1) # day number of year (0..364)
|
224
|
+
since_yday = since_yday - 1 if( since.leap? && since.mon > 2 )
|
225
|
+
date_yday = date - DateTime.new(date.year,1,1)
|
226
|
+
if( date.leap? )
|
227
|
+
if date_yday >= 60.0 # after Mar1
|
228
|
+
date_yday = date_yday - 1
|
229
|
+
elsif date_yday >= 59.0 # Feb29
|
230
|
+
raise("Feb.29 is specified, but calendar is #{calendar}.")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
days = (date.year - since.year)*365 + (date_yday - since_yday)
|
234
|
+
time = Units['days'].convert( days, tun )
|
235
|
+
when "360_day" # does not work perfectly
|
236
|
+
if date.day == 31
|
237
|
+
raise("day=31 is specified, but calendar is #{calendar}.")
|
238
|
+
end
|
239
|
+
if date.is_a?(DateTime)
|
240
|
+
date_hour,date_min,date_sec = date.hour,date.min,date.sec
|
241
|
+
else
|
242
|
+
date_hour,date_min,date_sec = 0,0,0
|
243
|
+
end
|
244
|
+
days = (date.year-since.year)*360 + (date.mon-since.mon)*30 +
|
245
|
+
(date.day-since.day) + Rational(date_hour-since.hour,24) +
|
246
|
+
Rational(date_min-since.min,1440) + Rational(date_sec-since.sec,86400)
|
247
|
+
time = Units['days'].convert( days.to_f, tun )
|
248
|
+
else
|
249
|
+
#raise("Unrecognized calendar: #{calendar}")
|
250
|
+
return nil
|
251
|
+
end
|
206
252
|
else
|
207
|
-
raise("Unrecognized time units #{tun.to_s}
|
253
|
+
#raise("Unrecognized time units #{tun.to_s}")
|
254
|
+
return nil
|
208
255
|
end
|
209
256
|
time = time.to_f
|
210
257
|
UNumeric[time, units]
|
211
258
|
end
|
212
259
|
|
260
|
+
|
261
|
+
# Always interpret y \d\d as 00\d\d and y \d as 000\d
|
262
|
+
# (Date in Ruby 1.9 interprets them as 20\d\d etc.)
|
263
|
+
def self::before_date_parse(str)
|
264
|
+
if /^\d\d-\d/ =~ str
|
265
|
+
str = "00"+str
|
266
|
+
elsif /^\d-\d/ =~ str
|
267
|
+
str = "00"+str
|
268
|
+
end
|
269
|
+
str
|
270
|
+
end
|
271
|
+
|
213
272
|
def val; @val; end
|
214
273
|
|
215
274
|
def units; @uni; end
|
@@ -250,7 +309,7 @@ module NumRu
|
|
250
309
|
|
251
310
|
# * eps_sec : Magic epsilon to prevent the round-off of DateTime [seconds].
|
252
311
|
# Recommended value is 0.1.
|
253
|
-
def to_datetime(eps_sec=0.0)
|
312
|
+
def to_datetime(eps_sec=0.0,calendar=nil)
|
254
313
|
time = self.val
|
255
314
|
sunits = self.units.to_s
|
256
315
|
/(.*) *since *(.*)/ =~ sunits
|
@@ -258,13 +317,47 @@ module NumRu
|
|
258
317
|
raise("Units mismatch. Requires time units that includes 'since'")
|
259
318
|
end
|
260
319
|
tun = Units[$1]
|
261
|
-
|
320
|
+
sincestr = $2.sub(/(^\d{1,2}-\d+-\d)/,'00\1')
|
321
|
+
#^ correction for Ruby 1.9 to prevent 1- or 2-digit years
|
322
|
+
# (e.g. 1, 02) to be interpreted as in 2000's (e.g., 2001, 2002)
|
323
|
+
since = DateTime.parse(UNumeric::before_date_parse(sincestr))
|
262
324
|
if( tun =~ Units['months since 0001-01-01'] )
|
263
325
|
datetime = since >> tun.convert( time, Units['months'] )
|
264
326
|
elsif( tun =~ Units['days since 0001-01-01'] )
|
265
|
-
|
327
|
+
case calendar
|
328
|
+
when nil, "gregorian", "standard"
|
329
|
+
# default: Julian calendar before 1582-10-15, Gregorian calendar afterward
|
330
|
+
datetime = since + tun.convert( time, Units['days'] )
|
331
|
+
when "proleptic_gregorian"
|
332
|
+
# Gregorian calendar extended to the past
|
333
|
+
since = DateTime.parse(UNumeric::before_date_parse(sincestr),false,Date::GREGORIAN)
|
334
|
+
datetime = since + tun.convert( time, Units['days'] )
|
335
|
+
when "noleap", "365_day"
|
336
|
+
since_yday = since - DateTime.new(since.year,1,1) # day number of year (0..364)
|
337
|
+
since_yday = since_yday - 1 if( since.leap? && since.mon > 2 )
|
338
|
+
days = since_yday + tun.convert( time, Units['days'] )
|
339
|
+
year = since.year + (days/365).to_i
|
340
|
+
date_yday = days%365 # day number of year (0..364)
|
341
|
+
datetime = DateTime.new(year,1,1) + date_yday
|
342
|
+
datetime = datetime + 1 if( datetime.leap? && date_yday >= 59 )
|
343
|
+
when "360_day" # does not work perfectly
|
344
|
+
since_day = since - DateTime.new(since.year,since.mon,1)
|
345
|
+
days = (since.mon-1)*30 + since_day + tun.convert( time, Units['days'] )
|
346
|
+
year = since.year + (days/360).to_i
|
347
|
+
mon = ((days%360)/30).to_i + 1
|
348
|
+
datetime = DateTime.new(year,mon,1) + days%30 # Feb29->Mar1,Feb30->Mar2
|
349
|
+
#datetime = DateTime.new(year,mon,days%30 + 1) # stops if Feb29,Feb30
|
350
|
+
if datetime.mon != mon # Feb29,Feb30
|
351
|
+
$stderr.print("cannot convert #{year}-#{mon}-#{(days%30+1).to_i} to DateTime instance\n")
|
352
|
+
return nil
|
353
|
+
end
|
354
|
+
else
|
355
|
+
#raise("Unrecognized calendar: #{calendar}")
|
356
|
+
return nil
|
357
|
+
end
|
266
358
|
else
|
267
|
-
raise("Unrecognized time units #{tun.to_s}
|
359
|
+
#raise("Unrecognized time units #{tun.to_s}")
|
360
|
+
return nil
|
268
361
|
end
|
269
362
|
if eps_sec != 0.0
|
270
363
|
datetime = datetime + eps_sec/8.64e4
|
data/lib/numru/gphys/varray.rb
CHANGED
@@ -263,6 +263,12 @@ NOMENCLATURE
|
|
263
263
|
* Float if the modulo is defined
|
264
264
|
* nil if modulo is not found
|
265
265
|
|
266
|
+
---axis_cyclic_extendible?
|
267
|
+
(meaningful only if self is a coordinate variable.)
|
268
|
+
Returns true if self is cyclic and it is suitable to exend
|
269
|
+
cyclically (having the distance between both ends
|
270
|
+
equal to (modulo - dx), where dx is the mean increment).
|
271
|
+
|
266
272
|
---coerce(other)
|
267
273
|
For Numeric operators. (If you do not know it, see a manual or book of Ruby)
|
268
274
|
|
@@ -325,7 +331,7 @@ These methods returns a NArray (not a VArray).
|
|
325
331
|
when nil
|
326
332
|
@attr = NumRu::Attribute.new
|
327
333
|
else
|
328
|
-
raise
|
334
|
+
raise TypeError, "#{attr.class} is unsupported for the 2nd arg"
|
329
335
|
end
|
330
336
|
end
|
331
337
|
|
@@ -409,11 +415,7 @@ These methods returns a NArray (not a VArray).
|
|
409
415
|
end
|
410
416
|
|
411
417
|
def ntype
|
412
|
-
|
413
|
-
__ntype(@ary)
|
414
|
-
else
|
415
|
-
__ntype(@varray.ary)
|
416
|
-
end
|
418
|
+
__ntype(typecode)
|
417
419
|
end
|
418
420
|
|
419
421
|
def name=(nm)
|
@@ -446,7 +448,7 @@ These methods returns a NArray (not a VArray).
|
|
446
448
|
if @mapping
|
447
449
|
@varray.file
|
448
450
|
else
|
449
|
-
|
451
|
+
return nil
|
450
452
|
end
|
451
453
|
end
|
452
454
|
|
@@ -545,7 +547,14 @@ These methods returns a NArray (not a VArray).
|
|
545
547
|
end
|
546
548
|
myunits = self.units
|
547
549
|
if myunits != to
|
548
|
-
|
550
|
+
if calendar = self.get_att("calendar")
|
551
|
+
date0 = UNumeric.new(0,myunits).to_datetime
|
552
|
+
un0 = UNumeric.from_date(date0,to,calendar)
|
553
|
+
offset = un0.to_f
|
554
|
+
gp = self + offset
|
555
|
+
else
|
556
|
+
gp = myunits.convert2(self, to)
|
557
|
+
end
|
549
558
|
gp.units = to
|
550
559
|
gp
|
551
560
|
else
|
@@ -625,7 +634,7 @@ These methods returns a NArray (not a VArray).
|
|
625
634
|
when /circular/i
|
626
635
|
true
|
627
636
|
when nil # 'topology' not defined
|
628
|
-
if attr['units']
|
637
|
+
if /degrees?_east/ =~ attr['units']
|
629
638
|
true # special treatment a common convention for the earth
|
630
639
|
else
|
631
640
|
nil # not defined --> nil
|
@@ -645,15 +654,34 @@ These methods returns a NArray (not a VArray).
|
|
645
654
|
else
|
646
655
|
attval[0]
|
647
656
|
end
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
657
|
+
elsif /degrees?_east/ =~ attr['units']
|
658
|
+
360.0 # special treatment: a common convention for the earth
|
659
|
+
elsif (tp = attr['topology']) and (/circular/i =~ tp)
|
660
|
+
un = Units[attr['units']]
|
661
|
+
if un == Units['degrees']
|
662
|
+
360.0
|
663
|
+
elsif un == Units['radian']
|
664
|
+
2*Math::PI
|
665
|
+
else
|
666
|
+
nil # cannot guess --> nil
|
667
|
+
end
|
668
|
+
else
|
669
|
+
nil # not defined --> nil
|
654
670
|
end
|
655
671
|
end
|
656
672
|
|
673
|
+
def axis_cyclic_extendible?
|
674
|
+
modulo = axis_modulo
|
675
|
+
return false if !modulo
|
676
|
+
v = val
|
677
|
+
width = (v[-1] - v[0]).abs
|
678
|
+
dx = width / (length-1)
|
679
|
+
eps = 1e-4
|
680
|
+
modulo = modulo.abs
|
681
|
+
extendible = ( ((width+dx) - modulo).abs < eps*modulo )
|
682
|
+
return extendible
|
683
|
+
end
|
684
|
+
|
657
685
|
### < NArray methods > ###
|
658
686
|
|
659
687
|
## ToDo: implement units handling
|
@@ -778,7 +806,7 @@ These methods returns a NArray (not a VArray).
|
|
778
806
|
ary = NArrayMiss.to_nam(vl)#{f}(vr)
|
779
807
|
end
|
780
808
|
va = VArray.new( ary, self.attr_copy, self.name )
|
781
|
-
va.units= self.units#{f}(other.units)
|
809
|
+
va.units= self.units#{f}(other.units) if "#{f}" != "**"
|
782
810
|
va
|
783
811
|
when Numeric, NArray, NArrayMiss, Array
|
784
812
|
vl = self.val
|
@@ -789,7 +817,7 @@ These methods returns a NArray (not a VArray).
|
|
789
817
|
ary = NArrayMiss.to_nam(vl)#{f}(vr)
|
790
818
|
end
|
791
819
|
va = VArray.new( ary, self.attr_copy, self.name )
|
792
|
-
if "#{f}" == "**"
|
820
|
+
if "#{f}" == "**" && other.is_a?(Numeric)
|
793
821
|
va.units= self.units#{f}(other)
|
794
822
|
end
|
795
823
|
va
|
@@ -966,6 +994,15 @@ These methods returns a NArray (not a VArray).
|
|
966
994
|
|
967
995
|
alias shape_current shape
|
968
996
|
|
997
|
+
## < marshal dump/load >
|
998
|
+
def marshal_dump
|
999
|
+
[@name, @mapping, @varray, @ary, @attr]
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
def marshal_load(ary)
|
1003
|
+
@name, @mapping, @varray, @ary, @attr = *ary
|
1004
|
+
end
|
1005
|
+
|
969
1006
|
## < private methods >
|
970
1007
|
private
|
971
1008
|
def __rubber_expansion( args )
|
@@ -998,8 +1035,8 @@ These methods returns a NArray (not a VArray).
|
|
998
1035
|
end
|
999
1036
|
narray
|
1000
1037
|
end
|
1001
|
-
def __ntype(
|
1002
|
-
case
|
1038
|
+
def __ntype(typecode)
|
1039
|
+
case typecode
|
1003
1040
|
when NArray::BYTE
|
1004
1041
|
"byte"
|
1005
1042
|
when NArray::SINT
|
@@ -1072,8 +1109,17 @@ if $0 == __FILE__
|
|
1072
1109
|
|
1073
1110
|
p '*axis conventions*'
|
1074
1111
|
p vx = VArray.new( NArray.int(6).indgen!, nil, 'x' )
|
1075
|
-
|
1112
|
+
|
1113
|
+
vx.put_att("topology","circular")
|
1076
1114
|
vx.set_att('modulo',[360.0])
|
1077
1115
|
vx.set_att('positive','down')
|
1078
1116
|
p vx.axis_draw_positive, vx.axis_cyclic?, vx.axis_modulo
|
1117
|
+
|
1118
|
+
p ' cyclic extendible:'
|
1119
|
+
p vx.axis_cyclic_extendible?
|
1120
|
+
vx.set_att('modulo',[6.0])
|
1121
|
+
p vx.axis_cyclic_extendible?
|
1122
|
+
|
1123
|
+
p '*typecode*'
|
1124
|
+
p vx.typecode, vx[0..1].typecode
|
1079
1125
|
end
|