rb-grib 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ #Total precipitation
2
+ 'Total precipitation' = {
3
+ discipline = 0 ;
4
+ parameterCategory = 1 ;
5
+ parameterNumber = 8 ;
6
+ }
7
+ #Total cloud cover
8
+ 'Total cloud cover' = {
9
+ discipline = 0 ;
10
+ parameterCategory = 6 ;
11
+ parameterNumber = 1 ;
12
+ }
13
+ #Low cloud cover
14
+ 'Low cloud cover' = {
15
+ discipline = 0 ;
16
+ parameterCategory = 6 ;
17
+ parameterNumber = 3 ;
18
+ }
19
+ #Medium cloud cover
20
+ 'Medium cloud cover' = {
21
+ discipline = 0 ;
22
+ parameterCategory = 6 ;
23
+ parameterNumber = 4 ;
24
+ }
25
+ #High cloud cover
26
+ 'High cloud cover' = {
27
+ discipline = 0 ;
28
+ parameterCategory = 6 ;
29
+ parameterNumber = 5 ;
30
+ }
@@ -0,0 +1,30 @@
1
+ #Total precipitation
2
+ '228' = {
3
+ discipline = 0 ;
4
+ parameterCategory = 1 ;
5
+ parameterNumber = 8 ;
6
+ }
7
+ #Total cloud cover
8
+ '164' = {
9
+ discipline = 0 ;
10
+ parameterCategory = 6 ;
11
+ parameterNumber = 1 ;
12
+ }
13
+ #Low cloud cover
14
+ '186' = {
15
+ discipline = 0 ;
16
+ parameterCategory = 6 ;
17
+ parameterNumber = 3 ;
18
+ }
19
+ #Medium cloud cover
20
+ '187' = {
21
+ discipline = 0 ;
22
+ parameterCategory = 6 ;
23
+ parameterNumber = 4 ;
24
+ }
25
+ #High cloud cover
26
+ '188' = {
27
+ discipline = 0 ;
28
+ parameterCategory = 6 ;
29
+ parameterNumber = 5 ;
30
+ }
@@ -0,0 +1,30 @@
1
+ #Total precipitation
2
+ 'tp' = {
3
+ discipline = 0 ;
4
+ parameterCategory = 1 ;
5
+ parameterNumber = 8 ;
6
+ }
7
+ #Total cloud cover
8
+ 'tcc' = {
9
+ discipline = 0 ;
10
+ parameterCategory = 6 ;
11
+ parameterNumber = 1 ;
12
+ }
13
+ #Low cloud cover
14
+ 'lcc' = {
15
+ discipline = 0 ;
16
+ parameterCategory = 6 ;
17
+ parameterNumber = 3 ;
18
+ }
19
+ #Medium cloud cover
20
+ 'mcc' = {
21
+ discipline = 0 ;
22
+ parameterCategory = 6 ;
23
+ parameterNumber = 4 ;
24
+ }
25
+ #High cloud cover
26
+ 'hcc' = {
27
+ discipline = 0 ;
28
+ parameterCategory = 6 ;
29
+ parameterNumber = 5 ;
30
+ }
@@ -0,0 +1,30 @@
1
+ #Total precipitation
2
+ 'kg m**-2' = {
3
+ discipline = 0 ;
4
+ parameterCategory = 1 ;
5
+ parameterNumber = 8 ;
6
+ }
7
+ #Total cloud cover
8
+ '%' = {
9
+ discipline = 0 ;
10
+ parameterCategory = 6 ;
11
+ parameterNumber = 1 ;
12
+ }
13
+ #Low cloud cover
14
+ '%' = {
15
+ discipline = 0 ;
16
+ parameterCategory = 6 ;
17
+ parameterNumber = 4 ;
18
+ }
19
+ #Medium cloud cover
20
+ '%' = {
21
+ discipline = 0 ;
22
+ parameterCategory = 6 ;
23
+ parameterNumber = 4 ;
24
+ }
25
+ #High cloud cover
26
+ '%' = {
27
+ discipline = 0 ;
28
+ parameterCategory = 6 ;
29
+ parameterNumber = 5 ;
30
+ }
@@ -1,8 +1,3 @@
1
- require "narray_miss"
2
- require "date"
3
- require "numru/grib.so"
4
-
5
-
6
1
  module NumRu
7
2
  class Grib
8
3
  class << self
@@ -45,45 +40,9 @@ module NumRu
45
40
  return false
46
41
  end
47
42
 
48
- def var_names
49
- parse_vars unless @vars
50
- return @vars.keys
51
- end
52
- def var(name)
53
- parse_vars unless @vars
54
- var = @vars[name]
55
- return nil if var.nil?
56
- return ::NumRu::GribVar.parse(self, var, name)
57
- end
58
43
  def inspect
59
44
  "Grib: #{path}"
60
45
  end
61
- private
62
- def parse_vars
63
- vars = Hash.new
64
- get_messages.each do |msg|
65
- name = msg.sname
66
- # zn = msg.z_sname
67
- # name << "_" << zn unless /\A(pl|isobaricIn)/ =~ zn
68
- hash = (vars[name] ||= Hash.new)
69
- nij = [msg.get_value("Ni"), msg.get_value("Nj"), msg.gtype, msg.z_type]
70
- if hash[nij]
71
- hash[nij][1].push msg
72
- else
73
- hash[nij] = [hash.length, [msg]]
74
- end
75
- end
76
- @vars = Hash.new
77
- vars.each do |name,hash|
78
- if hash.length == 1
79
- @vars[name] = hash.values[0][1]
80
- else
81
- hash.each do |k,ary|
82
- @vars[name+"_"+ary[0].to_s] = ary[1]
83
- end
84
- end
85
- end
86
- end
87
46
  end # class Grib
88
47
 
89
48
  class GribMessage
@@ -110,7 +69,7 @@ module NumRu
110
69
  get_value("indicatorOfTypeOfLevel") || get_value("typeOfLevel") || "level"
111
70
  end
112
71
  def z_value
113
- get_value("level")
72
+ get_value("levels") || get_value("level")
114
73
  end
115
74
  def z_units
116
75
  get_value("pressureUnits")
@@ -120,8 +79,8 @@ module NumRu
120
79
  h = get_value("dataTime").to_s.rjust(4,"0")
121
80
  return DateTime.parse(d << h)
122
81
  end
123
- def forecast_time
124
- get_value("forecastTime")
82
+ def step
83
+ get_value("step")
125
84
  end
126
85
  def time_interval
127
86
  get_value("lengthOfTimeRange")
@@ -180,136 +139,7 @@ module NumRu
180
139
 
181
140
  class GribVar
182
141
  Day0 = DateTime.new(1900)
183
- MAXNDIM = 7 # lon, lat, lev, t, forecastTime, timeInterval, ensemble
184
- class << self
185
- def parse(file,msgs,name)
186
- msg = msgs[0]
187
- va = ::NumRu::GribVar.new(file,name)
188
- va.put_att("long_name", msg.name)
189
- # va.put_att("standard_name",std_name)
190
- va.put_att("units",msg.units) if msg.units
191
- va.put_att("grid_type", msg.gtype)
192
- va.put_att("missing_value", [msg.missing_value]) if msg.missing_value
193
- vdim = Array.new
194
- xy_dims = 0
195
- msg.get_xy.sort{|x,y| x["ij"]<=>y["ij"] }.each do |xy|
196
- val = xy.delete("value")
197
- sname = xy.delete("short_name")
198
- ij = xy.delete("ij")
199
- if val.length > 1
200
- d = va.def_dim(sname, -1)
201
- d.put(val)
202
- xy.each{|k,v| d.put_att(k,v)}
203
- xy_dims += 1
204
- else
205
- #xy.each{|k,v| va.put_att(k,v)}
206
- end
207
- end
208
- z = Array.new
209
- t = Array.new
210
- ft = Array.new
211
- ti = Array.new
212
- en = Array.new
213
- hash = Hash.new
214
- msgs.each_with_index do |msg,i|
215
- zv = msg.z_value
216
- tv = get_time(msg.date)
217
- ftv = msg.forecast_time
218
- tiv = msg.time_interval
219
- env = msg.ensemble_member
220
- z.push zv
221
- t.push tv
222
- ft.push ftv
223
- ti.push tiv
224
- en.push env
225
- ary = [zv,tv,ftv,tiv,env]
226
- if hash[ary] # error
227
- m1 = msgs[hash[ary]]
228
- m2 = msgs[i]
229
- a1 = m1.get_keys.map{|k| [k,m1.get_value(k)]}
230
- a2 = m2.get_keys.map{|k| [k,m2.get_value(k)]}
231
- a = Array.new
232
- a1.length.times{|j| a.push [a1[j],a2[j]] if a1[j]!=a2[j]}
233
- warn "BUG: send the following message to the developers"
234
- p ary
235
- p a
236
- raise("error")
237
- end
238
- hash[ary] = i
239
- end
240
- hash = hash.invert
241
- [z, t, ft, ti, en].each{|a| a.uniq!}
242
- # [z, t, ft, ti, en].each{|a| a.uniq!; a.sort!}
243
- idx = Array.new(msgs.length) do |i|
244
- zv, tv, ftv, tiv, env = hash[i]
245
- [z.index(zv), t.index(tv), ft.index(ftv), ti.index(tiv), en.index(env)]
246
- end
247
- del_dims = Array.new
248
- if z.length == 1
249
- va.put_att("level_type", msg.z_type)
250
- va.put_att("level_value", [z[0]])
251
- va.put_att("level_units", msg.z_units) if msg.z_units
252
- del_dims.push xy_dims
253
- else
254
- d = va.def_dim(msg.z_sname, -1)
255
- d.put_att("long_name", msg.z_type)
256
- d.put_att("units", msg.z_units) if msg.z_units
257
- d.put(NArray.to_na(z))
258
- end
259
- if t.length == 1
260
- va.put_att("time", msg.date.to_s)
261
- del_dims.push xy_dims + 1
262
- else
263
- d = va.def_dim("time", -1)
264
- d.put_att("long_name","time")
265
- d.put_att("units","hours since #{Day0.strftime('%Y-%m-%d %H:%M:%S')}")
266
- d.put(NArray.to_na(t))
267
- end
268
- if ft.length == 1
269
- va.put_att("forecast_time", [msg.forecast_time]) if msg.forecast_time
270
- va.put_att("forcast_time_units", msg.step_units) if msg.step_units
271
- del_dims.push xy_dims + 2
272
- else
273
- d = va.def_dim("forecast_time", -1)
274
- d.put_att("long_name", "forecast_time")
275
- d.put_att("units", msg.step_units) if msg.step_units
276
- d.put(NArray.to_na(ft))
277
- end
278
- if ti.length == 1
279
- del_dims.push xy_dims + 3
280
- else
281
- d = va.def_dim("time_interval", -1)
282
- d.put_att("long_name", "time_interval")
283
- d.put_att("units", msg.step_units) if msg.step_units
284
- d.put(NArray.to_na(ti))
285
- end
286
- if en.length == 1
287
- del_dims.push xy_dims + 4
288
- else
289
- d = va.def_dim("member", -1)
290
- d.put_att("long_name", "ensemble_member")
291
- d.put(NArray.to_na(en))
292
- end
293
- va.set_msgs(msgs, idx, xy_dims, del_dims)
294
- return va
295
- end
296
- def get_time(date)
297
- ((date - Day0)*24).to_f
298
- end
299
- end # class << self
300
- attr_reader :file, :name
301
- def initialize(file,name)
302
- @file = file
303
- @name = name
304
- @attr = Hash.new
305
- @dims = Array.new
306
- end
307
- def set_msgs(msgs, idx, xy_dims, del_dims)
308
- @msgs = msgs
309
- @idx = idx
310
- @xy_dims = xy_dims
311
- @del_dims = del_dims
312
- end
142
+ MAXNDIM = 7 # lon, lat, lev, t, step, timeInterval, ensemble
313
143
  def rank
314
144
  @dims.length
315
145
  end
@@ -362,13 +192,14 @@ module NumRu
362
192
  mask = nil
363
193
  first = Array.new(rank-@xy_dims,0)
364
194
  if indices.length != 0
365
- if indices[0] == false
366
- indices[0] = [true]*(sha.length-indices.length+1)
367
- elsif indices[-1] == false
368
- indices[-1] = [true]*(sha.length-indices.length+1)
369
- elsif indices.include?(false) || indices.length != rank
370
- raise "invalid indices"
195
+ if indices.include?(false)
196
+ sha2 = sha.dup
197
+ sha2.delete(false)
198
+ raise ArgumentError, 'multiple "false" in indices' if sha.length - sha2.length > 1
199
+ indices[indices.index(false)] = [true]*(sha.length-indices.length+1)
200
+ indices.flatten!
371
201
  end
202
+
372
203
  rank.times{|n|
373
204
  ind = indices[n]
374
205
  case ind
@@ -422,7 +253,7 @@ module NumRu
422
253
  val.reshape!(*shape[0...@xy_dims])
423
254
  # val = msg.get_data[2].reshape!(*shape[0...@xy_dims])
424
255
  unless indices.length==0 || indices[0...@xy_dims].inject(true){|t,v| t &&= v==true}
425
- val = val[*indices[0...@xy_dims]]
256
+ val = val.slice(*indices[0...@xy_dims])
426
257
  end
427
258
  end
428
259
  (MAXNDIM-2).times do |i| index[i] = idx[i]-first[i] end
@@ -442,7 +273,126 @@ module NumRu
442
273
  alias :[] :get
443
274
  alias :val :get
444
275
  def inspect
445
- "GribVar: #{name} in #{@file.path}, [#{shape.join(",")}]"
276
+ "GribVar: #{name} in #{file.path}, [#{shape.join(",")}]"
277
+ end
278
+ private
279
+ def get_time(date)
280
+ (date - Day0).to_f*24
281
+ end
282
+ def init
283
+ @attr = Hash.new
284
+ @dims = Array.new
285
+ msgs = get_messages
286
+ msg = msgs[0]
287
+ put_att("long_name", msg.name)
288
+ # put_att("standard_name",std_name)
289
+ put_att("units",msg.units) if msg.units
290
+ put_att("grid_type", msg.gtype)
291
+ put_att("missing_value", [msg.missing_value]) if msg.missing_value
292
+ vdim = Array.new
293
+ xy_dims = 0
294
+ msg.get_xy.sort{|x,y| x["ij"]<=>y["ij"] }.each do |xy|
295
+ val = xy.delete("value")
296
+ sname = xy.delete("short_name")
297
+ ij = xy.delete("ij")
298
+ if val.length > 1
299
+ d = def_dim(sname, -1)
300
+ d.put(val)
301
+ xy.each{|k,v| d.put_att(k,v)}
302
+ xy_dims += 1
303
+ else
304
+ #xy.each{|k,v| va.put_att(k,v)}
305
+ end
306
+ end
307
+ z = Array.new
308
+ t = Array.new
309
+ st = Array.new
310
+ ti = Array.new
311
+ en = Array.new
312
+ hash = Hash.new
313
+ msgs.each_with_index do |msg,i|
314
+ zv = msg.z_value
315
+ tv = get_time(msg.date)
316
+ stv = msg.step
317
+ tiv = msg.time_interval
318
+ env = msg.ensemble_member
319
+ z.push zv
320
+ t.push tv
321
+ st.push stv
322
+ ti.push tiv
323
+ en.push env
324
+ ary = [zv,tv,stv,tiv,env]
325
+ if hash[ary] # error
326
+ m1 = msgs[hash[ary]]
327
+ m2 = msgs[i]
328
+ a1 = m1.get_keys.map{|k| [k,m1.get_value(k)]}
329
+ a2 = m2.get_keys.map{|k| [k,m2.get_value(k)]}
330
+ a = Array.new
331
+ a1.length.times{|j| a.push [a1[j],a2[j]] if a1[j]!=a2[j]}
332
+ warn "BUG: send the following message to the developers"
333
+ p self
334
+ p ary
335
+ p a
336
+ raise("error")
337
+ end
338
+ hash[ary] = i
339
+ end
340
+ [z, t, st, ti, en].each{|a| a.uniq!}
341
+ # [z, t, st, ti, en].each{|a| a.uniq!; a.sort!}
342
+ @idx = Array.new(msgs.length)
343
+ hash.each do |ary, i|
344
+ zv, tv, stv, tiv, env = ary
345
+ @idx[i] = [z.index(zv), t.index(tv), st.index(stv), ti.index(tiv), en.index(env)]
346
+ end
347
+ del_dims = Array.new
348
+ if z.length == 1
349
+ put_att("level_type", msg.z_type)
350
+ put_att("level_value", z[0].kind_of?(Numeric) ? [z[0]] : z[0])
351
+ put_att("level_units", msg.z_units) if msg.z_units
352
+ del_dims.push xy_dims
353
+ else
354
+ d = def_dim(msg.z_sname, -1)
355
+ d.put_att("long_name", msg.z_type)
356
+ d.put_att("units", msg.z_units) if msg.z_units
357
+ d.put(NArray.to_na(z))
358
+ end
359
+ if t.length == 1
360
+ put_att("time", msg.date.to_s)
361
+ del_dims.push xy_dims + 1
362
+ else
363
+ d = def_dim("time", -1)
364
+ d.put_att("long_name","time")
365
+ d.put_att("units","hours since #{Day0.strftime('%Y-%m-%d %H:%M:%S')}")
366
+ d.put(NArray.to_na(t))
367
+ end
368
+ if st.length == 1
369
+ put_att("step", [msg.step]) if msg.step
370
+ put_att("step_units", msg.step_units) if msg.step_units
371
+ del_dims.push xy_dims + 2
372
+ else
373
+ d = def_dim("step", -1)
374
+ d.put_att("long_name", "step")
375
+ d.put_att("units", msg.step_units) if msg.step_units
376
+ d.put(NArray.to_na(st))
377
+ end
378
+ if ti.length == 1
379
+ del_dims.push xy_dims + 3
380
+ else
381
+ d = def_dim("time_interval", -1)
382
+ d.put_att("long_name", "time_interval")
383
+ d.put_att("units", msg.step_units) if msg.step_units
384
+ d.put(NArray.to_na(ti))
385
+ end
386
+ if en.length == 1
387
+ del_dims.push xy_dims + 4
388
+ else
389
+ d = def_dim("member", -1)
390
+ d.put_att("long_name", "ensemble_member")
391
+ d.put(NArray.to_na(en))
392
+ end
393
+ @xy_dims = xy_dims
394
+ @del_dims = del_dims
395
+ @msgs = msgs
446
396
  end
447
397
  end # class GribVar
448
398