rb-grib 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +57 -0
- data/README.rdoc +34 -0
- data/Rakefile +1 -0
- data/ext/extconf.rb +6 -0
- data/ext/grib.c +435 -0
- data/lib/numru/grib.rb +2 -0
- data/lib/numru/grib/grib.rb +528 -0
- data/lib/numru/grib/version.rb +5 -0
- data/rb-grib.gemspec +25 -0
- metadata +76 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
Ruby-GRIB is copyrighted free software by Seiya Nishizawa and the
|
2
|
+
GFD Dennou Club.
|
3
|
+
You can redistribute it and/or modify it under either the terms of the
|
4
|
+
GPL, or the conditions below, which is idential to Ruby's license
|
5
|
+
(http://www.ruby-lang.org/en/LICENSE.txt):
|
6
|
+
|
7
|
+
1. You may make and give away verbatim copies of the source form of the
|
8
|
+
software without restriction, provided that you duplicate all of the
|
9
|
+
original copyright notices and associated disclaimers.
|
10
|
+
|
11
|
+
2. You may modify your copy of the software in any way, provided that
|
12
|
+
you do at least ONE of the following:
|
13
|
+
|
14
|
+
a) place your modifications in the Public Domain or otherwise
|
15
|
+
make them Freely Available, such as by posting said
|
16
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
17
|
+
the author to include your modifications in the software.
|
18
|
+
|
19
|
+
b) use the modified software only within your corporation or
|
20
|
+
organization.
|
21
|
+
|
22
|
+
c) rename any non-standard executables so the names do not conflict
|
23
|
+
with standard executables, which must also be provided.
|
24
|
+
|
25
|
+
d) make other distribution arrangements with the author.
|
26
|
+
|
27
|
+
3. You may distribute the software in object code or executable
|
28
|
+
form, provided that you do at least ONE of the following:
|
29
|
+
|
30
|
+
a) distribute the executables and library files of the software,
|
31
|
+
together with instructions (in the manual page or equivalent)
|
32
|
+
on where to get the original distribution.
|
33
|
+
|
34
|
+
b) accompany the distribution with the machine-readable source of
|
35
|
+
the software.
|
36
|
+
|
37
|
+
c) give non-standard executables non-standard names, with
|
38
|
+
instructions on where to get the original software distribution.
|
39
|
+
|
40
|
+
d) make other distribution arrangements with the author.
|
41
|
+
|
42
|
+
4. You may modify and include the part of the software into any other
|
43
|
+
software (possibly commercial). But some files in the distribution
|
44
|
+
are not written by the author, so that they are not under this terms.
|
45
|
+
|
46
|
+
See each file for the copying condition.
|
47
|
+
|
48
|
+
5. The scripts and library files supplied as input to or produced as
|
49
|
+
output from the software do not automatically fall under the
|
50
|
+
copyright of the software, but belong to whomever generated them,
|
51
|
+
and may be sold commercially, and may be aggregated with this
|
52
|
+
software.
|
53
|
+
|
54
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
55
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
56
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
57
|
+
PURPOSE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
= What's Ruby-GRIB
|
2
|
+
|
3
|
+
Ruby-GRIB is a class library to handle GRIB file.
|
4
|
+
|
5
|
+
= Requires
|
6
|
+
|
7
|
+
* Ruby (http://www.ruby-lang.org/)
|
8
|
+
* NArray (http://narray.rubyforge.org/index.html.en)
|
9
|
+
* GRIB API (http://www.ecmwf.int/products/data/software/grib_api.html)
|
10
|
+
|
11
|
+
= Install
|
12
|
+
|
13
|
+
# gem install rb-grib
|
14
|
+
|
15
|
+
= Usage
|
16
|
+
|
17
|
+
To use this library, put the following in your script.
|
18
|
+
require 'numru/grib'
|
19
|
+
|
20
|
+
|
21
|
+
= Example
|
22
|
+
|
23
|
+
require 'numru/grib'
|
24
|
+
include NumRu
|
25
|
+
|
26
|
+
filename = "test.grib"
|
27
|
+
grib = Grib.open(filename)
|
28
|
+
varnames = grib.var_names # => Array
|
29
|
+
varnames.each do |vname|
|
30
|
+
var = grib.var(vname) # => GribVar
|
31
|
+
dimnames = var.dim_names # => Array
|
32
|
+
ary = var.get # => NArray
|
33
|
+
end
|
34
|
+
grib.close
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/ext/extconf.rb
ADDED
data/ext/grib.c
ADDED
@@ -0,0 +1,435 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include "ruby.h"
|
4
|
+
#include "grib_api.h"
|
5
|
+
#include "narray.h"
|
6
|
+
|
7
|
+
|
8
|
+
#define MAX_VALUE_LENGTH 1024
|
9
|
+
|
10
|
+
VALUE cGrib;
|
11
|
+
VALUE cMessage;
|
12
|
+
|
13
|
+
typedef struct {
|
14
|
+
FILE *file;
|
15
|
+
char *fname;
|
16
|
+
grib_handle **handles;
|
17
|
+
int n;
|
18
|
+
} rg_file;
|
19
|
+
|
20
|
+
typedef struct {
|
21
|
+
VALUE file;
|
22
|
+
grib_handle *handle;
|
23
|
+
} rg_message;
|
24
|
+
|
25
|
+
static void
|
26
|
+
check_error(int code)
|
27
|
+
{
|
28
|
+
if (code)
|
29
|
+
rb_raise(rb_eRuntimeError, grib_get_error_message(code));
|
30
|
+
};
|
31
|
+
|
32
|
+
|
33
|
+
static void
|
34
|
+
message_free(rg_message *message)
|
35
|
+
{
|
36
|
+
if (message) {
|
37
|
+
free(message);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
static void
|
41
|
+
message_mark(rg_message *message)
|
42
|
+
{
|
43
|
+
if (message && message->file != Qnil)
|
44
|
+
rb_gc_mark(message->file);
|
45
|
+
}
|
46
|
+
static VALUE
|
47
|
+
message_alloc(VALUE klass)
|
48
|
+
{
|
49
|
+
rg_message *message = ALLOC(rg_message);
|
50
|
+
message->file = Qnil;
|
51
|
+
message->handle = NULL;
|
52
|
+
return Data_Wrap_Struct(klass, message_mark, message_free, message);
|
53
|
+
}
|
54
|
+
|
55
|
+
static void
|
56
|
+
file_close(rg_file *gfile)
|
57
|
+
{
|
58
|
+
int i;
|
59
|
+
if (gfile) {
|
60
|
+
if (gfile->handles) {
|
61
|
+
for (i=0; i<gfile->n; i++)
|
62
|
+
if (gfile->handles[i]) grib_handle_delete(gfile->handles[i]);
|
63
|
+
free(gfile->handles);
|
64
|
+
gfile->handles = NULL;
|
65
|
+
}
|
66
|
+
gfile->n = 0;
|
67
|
+
if (gfile->file) {
|
68
|
+
fclose(gfile->file);
|
69
|
+
gfile->file = NULL;
|
70
|
+
}
|
71
|
+
if (gfile->fname) {
|
72
|
+
free(gfile->fname);
|
73
|
+
gfile->fname = NULL;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
static void
|
78
|
+
file_free(rg_file *gfile)
|
79
|
+
{
|
80
|
+
if (gfile) {
|
81
|
+
file_close(gfile);
|
82
|
+
free(gfile);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
static VALUE
|
86
|
+
file_alloc(VALUE klass)
|
87
|
+
{
|
88
|
+
rg_file *gfile = ALLOC(rg_file);
|
89
|
+
gfile->file = NULL;
|
90
|
+
gfile->fname = NULL;
|
91
|
+
gfile->handles = NULL;
|
92
|
+
gfile->n = 0;
|
93
|
+
return Data_Wrap_Struct(klass, 0, file_free, gfile);
|
94
|
+
}
|
95
|
+
|
96
|
+
/*
|
97
|
+
NumRu::Grib.open(filename [, mode]) -> NumRu::Grib::File
|
98
|
+
*/
|
99
|
+
/*
|
100
|
+
static VALUE
|
101
|
+
rg_open(int argc, VALUE *argv, VALUE self)
|
102
|
+
{
|
103
|
+
VALUE rgfile = file_alloc(self);
|
104
|
+
return rg_file_initialize(argc, argv, rgfile);
|
105
|
+
}
|
106
|
+
*/
|
107
|
+
|
108
|
+
/*
|
109
|
+
NumRu::Grib.multi=(flag) -> True/False
|
110
|
+
*/
|
111
|
+
static VALUE
|
112
|
+
rg_multi(VALUE self, VALUE flag)
|
113
|
+
{
|
114
|
+
if (flag == Qtrue)
|
115
|
+
grib_multi_support_on(0);
|
116
|
+
else if (flag == Qfalse)
|
117
|
+
grib_multi_support_off(0);
|
118
|
+
else
|
119
|
+
rb_raise(rb_eArgError, "flag must be true or false");
|
120
|
+
return flag;
|
121
|
+
}
|
122
|
+
|
123
|
+
/*
|
124
|
+
NumRu::Grib#initialize(filename, [, mode])
|
125
|
+
*/
|
126
|
+
static VALUE
|
127
|
+
rg_file_initialize(int argc, VALUE *argv, VALUE self)
|
128
|
+
{
|
129
|
+
char *fname, *mode;
|
130
|
+
VALUE rfname, rmode;
|
131
|
+
rb_scan_args(argc, argv, "11", &rfname, &rmode);
|
132
|
+
fname = StringValueCStr(rfname);
|
133
|
+
if (rmode == Qnil)
|
134
|
+
mode = "r";
|
135
|
+
else
|
136
|
+
mode = StringValueCStr(rmode);
|
137
|
+
|
138
|
+
FILE *file = fopen(fname, mode);
|
139
|
+
if (!file)
|
140
|
+
rb_raise(rb_eRuntimeError, "unable to open file %s", fname);
|
141
|
+
|
142
|
+
rg_file *gfile;
|
143
|
+
Data_Get_Struct(self, rg_file, gfile);
|
144
|
+
gfile->file = file;
|
145
|
+
gfile->fname = ALLOC_N(char, strlen(fname)+1);
|
146
|
+
strcpy(gfile->fname, fname);
|
147
|
+
|
148
|
+
int n = 0;
|
149
|
+
int error;
|
150
|
+
grib_handle *handle;
|
151
|
+
while ((handle = grib_handle_new_from_file(0, file, &error))) {
|
152
|
+
check_error(error);
|
153
|
+
if (handle == NULL)
|
154
|
+
rb_raise(rb_eRuntimeError, "unable to create handle in %s", fname);
|
155
|
+
grib_handle_delete(handle);
|
156
|
+
n++;
|
157
|
+
}
|
158
|
+
rewind(file);
|
159
|
+
grib_handle **handles = ALLOC_N(grib_handle*, n);
|
160
|
+
int i;
|
161
|
+
for (i=0; i<n; i++) handles[i] = NULL;
|
162
|
+
for (i=0; i<n; i++) {
|
163
|
+
handle = grib_handle_new_from_file(0, file, &error);
|
164
|
+
check_error(error);
|
165
|
+
if (handle == NULL)
|
166
|
+
rb_raise(rb_eRuntimeError, "unable to create handle in %s", fname);
|
167
|
+
handles[i] = handle;
|
168
|
+
}
|
169
|
+
gfile->n = n;
|
170
|
+
gfile->handles = handles;
|
171
|
+
return self;
|
172
|
+
}
|
173
|
+
/*
|
174
|
+
NumRu::Grib#close() -> nil
|
175
|
+
*/
|
176
|
+
static VALUE
|
177
|
+
rg_file_close(VALUE self)
|
178
|
+
{
|
179
|
+
rg_file *gfile;
|
180
|
+
Data_Get_Struct(self, rg_file, gfile);
|
181
|
+
file_close(gfile);
|
182
|
+
return Qnil;
|
183
|
+
}
|
184
|
+
|
185
|
+
/*
|
186
|
+
NumRu::Grib#get_messages() -> Array
|
187
|
+
*/
|
188
|
+
static VALUE
|
189
|
+
rg_file_get_messages(VALUE self)
|
190
|
+
{
|
191
|
+
rg_file *gfile;
|
192
|
+
Data_Get_Struct(self, rg_file, gfile);
|
193
|
+
VALUE ary = rb_ary_new2(gfile->n);
|
194
|
+
rg_message *message;
|
195
|
+
VALUE rmessage;
|
196
|
+
int i;
|
197
|
+
for (i=0; i<gfile->n; i++) {
|
198
|
+
rmessage = message_alloc(cMessage);
|
199
|
+
Data_Get_Struct(rmessage, rg_message, message);
|
200
|
+
message->file = self;
|
201
|
+
message->handle = gfile->handles[i];
|
202
|
+
rb_ary_store(ary, i, rmessage);
|
203
|
+
}
|
204
|
+
return ary;
|
205
|
+
}
|
206
|
+
|
207
|
+
/*
|
208
|
+
NumRu::Grib#path() -> String
|
209
|
+
*/
|
210
|
+
static VALUE
|
211
|
+
rg_file_path(VALUE self)
|
212
|
+
{
|
213
|
+
rg_file *gfile;
|
214
|
+
Data_Get_Struct(self, rg_file, gfile);
|
215
|
+
return rb_str_new2(gfile->fname);
|
216
|
+
}
|
217
|
+
|
218
|
+
/*
|
219
|
+
NumRu::GribMessage#initialize()
|
220
|
+
*/
|
221
|
+
static VALUE
|
222
|
+
rg_message_initialize(VALUE self, VALUE file)
|
223
|
+
{
|
224
|
+
rg_message *message;
|
225
|
+
Data_Get_Struct(self, rg_message, message);
|
226
|
+
message->file = file;
|
227
|
+
return self;
|
228
|
+
}
|
229
|
+
|
230
|
+
/*
|
231
|
+
NumRu::GribMessage#get_keys() -> Array
|
232
|
+
*/
|
233
|
+
static VALUE
|
234
|
+
rg_message_get_keys(int argc, VALUE *argv, VALUE self)
|
235
|
+
{
|
236
|
+
VALUE rflag, rns;
|
237
|
+
unsigned long flag = GRIB_KEYS_ITERATOR_SKIP_READ_ONLY || GRIB_KEYS_ITERATOR_SKIP_COMPUTED;
|
238
|
+
// unsigned long flag = GRIB_KEYS_ITERATOR_ALL_KEYS;
|
239
|
+
char *name_space = NULL;
|
240
|
+
rb_scan_args(argc, argv, "02", &rflag, &rns);
|
241
|
+
if (rflag != Qnil) flag = NUM2ULONG(rflag);
|
242
|
+
if (rns != Qnil) name_space = StringValueCStr(rns);
|
243
|
+
|
244
|
+
rg_message *message;
|
245
|
+
Data_Get_Struct(self, rg_message, message);
|
246
|
+
grib_keys_iterator *ki = NULL;
|
247
|
+
ki = grib_keys_iterator_new(message->handle, flag, name_space);
|
248
|
+
if (!ki)
|
249
|
+
rb_raise(rb_eRuntimeError, "unable to create key iterator");
|
250
|
+
VALUE keys = rb_ary_new();
|
251
|
+
while (grib_keys_iterator_next(ki)) {
|
252
|
+
const char *name = grib_keys_iterator_get_name(ki);
|
253
|
+
rb_ary_push(keys, rb_str_new2(name));
|
254
|
+
}
|
255
|
+
grib_keys_iterator_delete(ki);
|
256
|
+
return keys;
|
257
|
+
}
|
258
|
+
|
259
|
+
/*
|
260
|
+
NumRu::GribMessage#get_value(name [,type]) -> String
|
261
|
+
*/
|
262
|
+
static VALUE
|
263
|
+
rg_message_get_value(int argc, VALUE *argv, VALUE self)
|
264
|
+
{
|
265
|
+
VALUE rname, rtype;
|
266
|
+
rb_scan_args(argc, argv, "11", &rname, &rtype);
|
267
|
+
char *name = StringValueCStr(rname);
|
268
|
+
int type;
|
269
|
+
rg_message *message;
|
270
|
+
Data_Get_Struct(self, rg_message, message);
|
271
|
+
if (rtype == Qnil)
|
272
|
+
grib_get_native_type(message->handle, name, &type);
|
273
|
+
else
|
274
|
+
type = NUM2INT(rtype);
|
275
|
+
size_t len;
|
276
|
+
VALUE ret = Qnil;
|
277
|
+
grib_get_size(message->handle, name, &len);
|
278
|
+
switch (type) {
|
279
|
+
case GRIB_TYPE_UNDEFINED:
|
280
|
+
case GRIB_TYPE_STRING:
|
281
|
+
case GRIB_TYPE_LABEL:
|
282
|
+
{
|
283
|
+
char value[MAX_VALUE_LENGTH];
|
284
|
+
len = MAX_VALUE_LENGTH;
|
285
|
+
bzero(value, len);
|
286
|
+
if (grib_get_string(message->handle, name, value, &len) == GRIB_SUCCESS) {
|
287
|
+
if (value[len-1] == '\0') len--;
|
288
|
+
ret = rb_str_new(value, len);
|
289
|
+
}
|
290
|
+
}
|
291
|
+
break;
|
292
|
+
case GRIB_TYPE_BYTES:
|
293
|
+
{
|
294
|
+
unsigned char value[MAX_VALUE_LENGTH];
|
295
|
+
len = MAX_VALUE_LENGTH;
|
296
|
+
bzero(value, len);
|
297
|
+
if (grib_get_bytes(message->handle, name, value, &len) == GRIB_SUCCESS)
|
298
|
+
ret = rb_str_new((char*)value, len);
|
299
|
+
}
|
300
|
+
break;
|
301
|
+
case GRIB_TYPE_LONG:
|
302
|
+
{
|
303
|
+
if (len == 1) {
|
304
|
+
long l;
|
305
|
+
if (rtype == Qnil) {
|
306
|
+
char value[MAX_VALUE_LENGTH];
|
307
|
+
len = MAX_VALUE_LENGTH;
|
308
|
+
bzero(value, len);
|
309
|
+
if (grib_get_string(message->handle, name, value, &len) == GRIB_SUCCESS) {
|
310
|
+
check_error(grib_get_long(message->handle, name, &l));
|
311
|
+
if (atol(value) == l)
|
312
|
+
ret = LONG2NUM(l);
|
313
|
+
else
|
314
|
+
ret = rb_str_new2(value);
|
315
|
+
}
|
316
|
+
} else {
|
317
|
+
check_error(grib_get_long(message->handle, name, &l));
|
318
|
+
ret = LONG2NUM(l);
|
319
|
+
}
|
320
|
+
} else {
|
321
|
+
int shape[1];
|
322
|
+
struct NARRAY *nary;
|
323
|
+
shape[0] = len;
|
324
|
+
VALUE rnary = na_make_object(NA_LINT, 1, shape, cNArray);
|
325
|
+
GetNArray(rnary, nary);
|
326
|
+
if (grib_get_long_array(message->handle, name, (long*)nary->ptr, &len) == GRIB_SUCCESS)
|
327
|
+
ret = rnary;
|
328
|
+
}
|
329
|
+
}
|
330
|
+
break;
|
331
|
+
case GRIB_TYPE_DOUBLE:
|
332
|
+
{
|
333
|
+
if (len == 1) {
|
334
|
+
double value;
|
335
|
+
if (grib_get_double(message->handle, name, &value) == GRIB_SUCCESS)
|
336
|
+
ret = rb_float_new(value);
|
337
|
+
} else {
|
338
|
+
int shape[1];
|
339
|
+
struct NARRAY *nary;
|
340
|
+
shape[0] = len;
|
341
|
+
VALUE rnary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
|
342
|
+
GetNArray(rnary, nary);
|
343
|
+
if (grib_get_double_array(message->handle, name, (double*)nary->ptr, &len) == GRIB_SUCCESS)
|
344
|
+
ret = rnary;
|
345
|
+
}
|
346
|
+
}
|
347
|
+
break;
|
348
|
+
default:
|
349
|
+
rb_raise(rb_eArgError, "type is invalid: %d", type);
|
350
|
+
}
|
351
|
+
return ret;
|
352
|
+
}
|
353
|
+
|
354
|
+
/*
|
355
|
+
NumRu::GribMessage#get_data() -> [lon, lat, value]
|
356
|
+
*/
|
357
|
+
static VALUE
|
358
|
+
rg_message_get_data(VALUE self)
|
359
|
+
{
|
360
|
+
rg_message *message;
|
361
|
+
Data_Get_Struct(self, rg_message, message);
|
362
|
+
int error;
|
363
|
+
grib_iterator *iter = grib_iterator_new(message->handle, 0, &error);
|
364
|
+
check_error(error);
|
365
|
+
long np;
|
366
|
+
check_error(grib_get_long(message->handle, "numberOfPoints", &np));
|
367
|
+
double *lon, *lat, *value;
|
368
|
+
VALUE na_lon, na_lat, na_value;
|
369
|
+
struct NARRAY *nary;
|
370
|
+
int shape[1];
|
371
|
+
shape[0] = np;
|
372
|
+
na_lon = na_make_object(NA_DFLOAT, 1, shape, cNArray);
|
373
|
+
GetNArray(na_lon, nary);
|
374
|
+
lon = (double*) nary->ptr;
|
375
|
+
na_lat = na_make_object(NA_DFLOAT, 1, shape, cNArray);
|
376
|
+
GetNArray(na_lat, nary);
|
377
|
+
lat = (double*) nary->ptr;
|
378
|
+
na_value = na_make_object(NA_DFLOAT, 1, shape, cNArray);
|
379
|
+
GetNArray(na_value, nary);
|
380
|
+
value = (double*) nary->ptr;
|
381
|
+
int n = 0;
|
382
|
+
double lo, la, val;
|
383
|
+
while( grib_iterator_next(iter, &la, &lo, &val) ) {
|
384
|
+
lat[n] = la;
|
385
|
+
lon[n] = lo;
|
386
|
+
value[n] = val;
|
387
|
+
n++;
|
388
|
+
}
|
389
|
+
grib_iterator_delete(iter);
|
390
|
+
return rb_ary_new3(3, na_lon, na_lat, na_value);
|
391
|
+
}
|
392
|
+
|
393
|
+
|
394
|
+
|
395
|
+
void Init_grib()
|
396
|
+
{
|
397
|
+
rb_require("narray");
|
398
|
+
|
399
|
+
VALUE mNumRu = rb_define_module("NumRu");
|
400
|
+
cGrib = rb_define_class_under(mNumRu, "Grib", rb_cObject);
|
401
|
+
cMessage = rb_define_class_under(mNumRu, "GribMessage", rb_cObject);
|
402
|
+
|
403
|
+
grib_multi_support_on(0);
|
404
|
+
|
405
|
+
//rb_define_singleton_method(cGrib, "open", rg_open, -1);
|
406
|
+
rb_define_singleton_method(cGrib, "multi=", rg_multi, 1);
|
407
|
+
|
408
|
+
rb_define_alloc_func(cGrib, file_alloc);
|
409
|
+
rb_define_method(cGrib, "initialize", rg_file_initialize, -1);
|
410
|
+
rb_define_method(cGrib, "close", rg_file_close, 0);
|
411
|
+
rb_define_method(cGrib, "get_messages", rg_file_get_messages, 0);
|
412
|
+
rb_define_method(cGrib, "path", rg_file_path, 0);
|
413
|
+
|
414
|
+
rb_define_alloc_func(cMessage, message_alloc);
|
415
|
+
rb_define_method(cMessage, "initialize", rg_message_initialize, 1);
|
416
|
+
rb_define_method(cMessage, "get_keys", rg_message_get_keys, -1);
|
417
|
+
rb_define_method(cMessage, "get_value", rg_message_get_value, -1);
|
418
|
+
rb_define_method(cMessage, "get_data", rg_message_get_data, 0);
|
419
|
+
|
420
|
+
rb_define_const(cGrib, "TYPE_UNDEFINED", INT2NUM(GRIB_TYPE_UNDEFINED));
|
421
|
+
rb_define_const(cGrib, "TYPE_LONG", INT2NUM(GRIB_TYPE_LONG));
|
422
|
+
rb_define_const(cGrib, "TYPE_DOUBLE", INT2NUM(GRIB_TYPE_DOUBLE));
|
423
|
+
rb_define_const(cGrib, "TYPE_STRING", INT2NUM(GRIB_TYPE_STRING));
|
424
|
+
rb_define_const(cGrib, "TYPE_BYTES", INT2NUM(GRIB_TYPE_BYTES));
|
425
|
+
rb_define_const(cGrib, "TYPE_SECTION", INT2NUM(GRIB_TYPE_SECTION));
|
426
|
+
rb_define_const(cGrib, "TYPE_LABEL", INT2NUM(GRIB_TYPE_LABEL));
|
427
|
+
rb_define_const(cGrib, "TYPE_MISSING", INT2NUM(GRIB_TYPE_MISSING));
|
428
|
+
|
429
|
+
rb_define_const(cGrib, "NEAREST_SAME_GRID", ULONG2NUM(GRIB_NEAREST_SAME_GRID));
|
430
|
+
rb_define_const(cGrib, "NEAREST_SAME_DATA", ULONG2NUM(GRIB_NEAREST_SAME_DATA));
|
431
|
+
rb_define_const(cGrib, "NEAREST_SAME_POINT", ULONG2NUM(GRIB_NEAREST_SAME_POINT));
|
432
|
+
|
433
|
+
rb_define_const(cGrib, "KEYS_ITERATOR_ALL_KEYS", ULONG2NUM(GRIB_KEYS_ITERATOR_ALL_KEYS));
|
434
|
+
rb_define_const(cGrib, "KEYS_ITERATOR_SKIP_READ_ONLY", ULONG2NUM(GRIB_KEYS_ITERATOR_SKIP_READ_ONLY));
|
435
|
+
}
|
data/lib/numru/grib.rb
ADDED
@@ -0,0 +1,528 @@
|
|
1
|
+
require "narray_miss"
|
2
|
+
require "date"
|
3
|
+
require "numru/grib.so"
|
4
|
+
|
5
|
+
|
6
|
+
module NumRu
|
7
|
+
class Grib
|
8
|
+
class << self
|
9
|
+
# cache due to momery leak in the original grib_api library
|
10
|
+
@@gribs = Hash.new
|
11
|
+
def is_a_Grib?(fname)
|
12
|
+
is = false
|
13
|
+
File.open(fname) do |file|
|
14
|
+
is = (file.read(4) == "GRIB")
|
15
|
+
end
|
16
|
+
return is
|
17
|
+
end
|
18
|
+
alias :_new :new
|
19
|
+
def new(fname, mode="r")
|
20
|
+
key = [fname,mode]
|
21
|
+
if (obj = @@gribs[key])
|
22
|
+
obj[1] += 1
|
23
|
+
return obj[0]
|
24
|
+
else
|
25
|
+
grib = _new(fname, mode)
|
26
|
+
@@gribs[key] = [grib, 1]
|
27
|
+
return grib
|
28
|
+
end
|
29
|
+
end
|
30
|
+
alias :open :new
|
31
|
+
end # class << self
|
32
|
+
|
33
|
+
alias :_close :close
|
34
|
+
def close
|
35
|
+
@@gribs.each do |k, val|
|
36
|
+
if self == val[0]
|
37
|
+
val[1] -= 1
|
38
|
+
if val[1] < 1
|
39
|
+
_close
|
40
|
+
@@gribs.delete(k)
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
|
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
|
+
def inspect
|
59
|
+
"Grib: #{path}"
|
60
|
+
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
|
+
end # class Grib
|
88
|
+
|
89
|
+
class GribMessage
|
90
|
+
def name
|
91
|
+
n = get_value("name")
|
92
|
+
return n if (n && n != "unknown")
|
93
|
+
get_value("parameterName") || get_value("indicatorOfParameter")
|
94
|
+
end
|
95
|
+
def sname
|
96
|
+
sn = get_value("shortName")
|
97
|
+
return sn if (sn && sn != "unknown")
|
98
|
+
"id" + (get_value("indicatorOfParameter", ::NumRu::Grib::TYPE_LONG) || get_value("parameterNumber", ::NumRu::Grib::TYPE_LONG)).to_s
|
99
|
+
end
|
100
|
+
def units
|
101
|
+
get_value("parameterUnits") || get_value("units")
|
102
|
+
end
|
103
|
+
alias :unit :units
|
104
|
+
def z_type
|
105
|
+
zt = get_value("typeOfLevel")
|
106
|
+
return zt if zt && zt != "unknown"
|
107
|
+
z_sname
|
108
|
+
end
|
109
|
+
def z_sname
|
110
|
+
get_value("indicatorOfTypeOfLevel") || get_value("typeOfLevel") || "level"
|
111
|
+
end
|
112
|
+
def z_value
|
113
|
+
get_value("level")
|
114
|
+
end
|
115
|
+
def z_units
|
116
|
+
get_value("pressureUnits")
|
117
|
+
end
|
118
|
+
def date
|
119
|
+
d = get_value("dataDate").to_s.rjust(8,"0")
|
120
|
+
h = get_value("dataTime").to_s.rjust(4,"0")
|
121
|
+
return DateTime.parse(d << h)
|
122
|
+
end
|
123
|
+
def forecast_time
|
124
|
+
get_value("forecastTime")
|
125
|
+
end
|
126
|
+
def time_interval
|
127
|
+
get_value("lengthOfTimeRange")
|
128
|
+
end
|
129
|
+
def step_units
|
130
|
+
get_value("stepUnits")
|
131
|
+
end
|
132
|
+
MEMBER_NAME = {1 => "", 2 => "n", 3 => "p"}
|
133
|
+
def ensemble_member
|
134
|
+
pn = get_value("perturbationNumber")
|
135
|
+
te = get_value("typeOfEnsembleForecast")
|
136
|
+
name = ""
|
137
|
+
name << pn.to_s if pn
|
138
|
+
name << (MEMBER_NAME[te] || te.to_s) if te
|
139
|
+
name
|
140
|
+
end
|
141
|
+
def gtype
|
142
|
+
get_value("typeOfGrid")
|
143
|
+
end
|
144
|
+
def missing_value
|
145
|
+
get_value("missingValue")
|
146
|
+
end
|
147
|
+
def get_xy
|
148
|
+
lo, la, = get_data
|
149
|
+
case gtype
|
150
|
+
when "regular_ll", "regular_gg"
|
151
|
+
lon = Hash.new
|
152
|
+
lat = Hash.new
|
153
|
+
if get_value("jPointsAreConsecutive") == 1
|
154
|
+
lon["ij"] = 1
|
155
|
+
lat["ij"] = 0
|
156
|
+
shape = [get_value("Nj"), get_value("Ni")]
|
157
|
+
else
|
158
|
+
lon["ij"] = 0
|
159
|
+
lat["ij"] = 1
|
160
|
+
shape = [get_value("Ni"), get_value("Nj")]
|
161
|
+
end
|
162
|
+
lo.reshape!(*shape)
|
163
|
+
la.reshape!(*shape)
|
164
|
+
lon["short_name"] = "lon"
|
165
|
+
lon["long_name"] = "longitude"
|
166
|
+
lon["units"] = "degrees_east"
|
167
|
+
idx = [0,0]; idx[lon["ij"]] = true
|
168
|
+
lon["value"] = lo[*idx]
|
169
|
+
lat["short_name"] = "lat"
|
170
|
+
lat["long_name"] = "latitude"
|
171
|
+
lat["units"] = "degrees_north"
|
172
|
+
idx = [0,0]; idx[lat["ij"]] = true
|
173
|
+
lat["value"] = la[*idx]
|
174
|
+
return [lon,lat]
|
175
|
+
else
|
176
|
+
raise "not defined yet: #{gtype}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end # class GribMessage
|
180
|
+
|
181
|
+
class GribVar
|
182
|
+
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
|
313
|
+
def rank
|
314
|
+
@dims.length
|
315
|
+
end
|
316
|
+
alias :ndims :rank
|
317
|
+
def total
|
318
|
+
@dims.inject(1){|t,d| t*d.length}
|
319
|
+
end
|
320
|
+
def dim_names
|
321
|
+
@dims.collect{|d| d.name}
|
322
|
+
end
|
323
|
+
def shape
|
324
|
+
@dims.collect{|d| d.length}
|
325
|
+
end
|
326
|
+
def dim(index)
|
327
|
+
index = dim_names.index(index) if String===index
|
328
|
+
return nil if index.nil?
|
329
|
+
@dims[index]
|
330
|
+
end
|
331
|
+
def def_dim(name,index)
|
332
|
+
d = ::NumRu::GribDim.new(self,name)
|
333
|
+
if index == -1
|
334
|
+
@dims.push(d)
|
335
|
+
else
|
336
|
+
@dims[index] = d
|
337
|
+
end
|
338
|
+
return d
|
339
|
+
end
|
340
|
+
def put_att(key,val)
|
341
|
+
@attr[key] = val
|
342
|
+
end
|
343
|
+
alias :set_att :put_att
|
344
|
+
def att(key)
|
345
|
+
@attr[key]
|
346
|
+
end
|
347
|
+
def att_names
|
348
|
+
@attr.keys
|
349
|
+
end
|
350
|
+
def typecode
|
351
|
+
if missing_value
|
352
|
+
NArrayMiss::DFLOAT
|
353
|
+
else
|
354
|
+
NArray::DFLOAT
|
355
|
+
end
|
356
|
+
end
|
357
|
+
def missing_value
|
358
|
+
@msgs[0].missing_value
|
359
|
+
end
|
360
|
+
def get(*indices)
|
361
|
+
sha = shape
|
362
|
+
mask = nil
|
363
|
+
first = Array.new(rank-@xy_dims,0)
|
364
|
+
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"
|
371
|
+
end
|
372
|
+
rank.times{|n|
|
373
|
+
ind = indices[n]
|
374
|
+
case ind
|
375
|
+
when true
|
376
|
+
indices[n] = 0..sha[n]-1
|
377
|
+
when Fixnum
|
378
|
+
sha[n] = 1
|
379
|
+
when Range
|
380
|
+
f = ind.first
|
381
|
+
e = ind.end
|
382
|
+
e = sha[n]-1 if e==-1
|
383
|
+
e -= 1 if ind.exclude_end?
|
384
|
+
sha[n] = e-f+1
|
385
|
+
indices[n] = f..e
|
386
|
+
else
|
387
|
+
raise "invalid indices"
|
388
|
+
end
|
389
|
+
}
|
390
|
+
if rank > @xy_dims
|
391
|
+
mask = NArray.byte(*shape[@xy_dims..-1])
|
392
|
+
mask[*indices[@xy_dims..-1]] = 1
|
393
|
+
(rank-@xy_dims).times do |i|
|
394
|
+
ind = indices[@xy_dims+i]
|
395
|
+
case ind
|
396
|
+
when Fixnum
|
397
|
+
first[i] = ind
|
398
|
+
when Range
|
399
|
+
first[i] = ind.first
|
400
|
+
first[i] += shape[@xy_dims+i] if first[i] < 0
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
shape2 = shape.dup
|
407
|
+
sha2 = sha.dup
|
408
|
+
@del_dims.each do |i|
|
409
|
+
shape2.insert(i,1)
|
410
|
+
sha2.insert(i,1)
|
411
|
+
first.insert(i-@xy_dims,0)
|
412
|
+
end
|
413
|
+
mask.reshape!(*shape2[@xy_dims..-1]) if mask
|
414
|
+
|
415
|
+
value = missing_value ? NArrayMiss.sfloat(*sha2) : NArray.sfloat(*sha2)
|
416
|
+
index = Array.new(MAXNDIM-2)
|
417
|
+
@msgs.each_with_index do |msg,i|
|
418
|
+
idx = @idx[i]
|
419
|
+
next if (mask && mask[*idx]==0)
|
420
|
+
val = msg.get_value("values")
|
421
|
+
if @xy_dims > 0
|
422
|
+
val.reshape!(*shape[0...@xy_dims])
|
423
|
+
# val = msg.get_data[2].reshape!(*shape[0...@xy_dims])
|
424
|
+
unless indices.length==0 || indices[0...@xy_dims].inject(true){|t,v| t &&= v==true}
|
425
|
+
val = val[*indices[0...@xy_dims]]
|
426
|
+
end
|
427
|
+
end
|
428
|
+
(MAXNDIM-2).times do |i| index[i] = idx[i]-first[i] end
|
429
|
+
value[*(Array.new(@xy_dims,true)+index)] = val
|
430
|
+
end
|
431
|
+
ns = sha.length
|
432
|
+
ns.times do |ii|
|
433
|
+
i = ns-ii-1
|
434
|
+
sha.delete_at(i) if indices[i].kind_of?(Fixnum)
|
435
|
+
end
|
436
|
+
value.reshape!(*sha)
|
437
|
+
if missing_value
|
438
|
+
value.set_mask value.get_array!.ne(missing_value)
|
439
|
+
end
|
440
|
+
return value
|
441
|
+
end
|
442
|
+
alias :[] :get
|
443
|
+
alias :val :get
|
444
|
+
def inspect
|
445
|
+
"GribVar: #{name} in #{@file.path}, [#{shape.join(",")}]"
|
446
|
+
end
|
447
|
+
end # class GribVar
|
448
|
+
|
449
|
+
class GribDim
|
450
|
+
attr_reader :var, :length, :name
|
451
|
+
def initialize(var,name)
|
452
|
+
@var = var
|
453
|
+
@name = name
|
454
|
+
@attr = Hash.new
|
455
|
+
end
|
456
|
+
alias :total :length
|
457
|
+
def get
|
458
|
+
@ary
|
459
|
+
end
|
460
|
+
def typecode
|
461
|
+
if NArray===@ary
|
462
|
+
@ary.typecode
|
463
|
+
elsif Array===@ary
|
464
|
+
@ary[0]["value"].typecode
|
465
|
+
end
|
466
|
+
end
|
467
|
+
def val
|
468
|
+
return @ary
|
469
|
+
end
|
470
|
+
def [](*ind)
|
471
|
+
return val[*ind]
|
472
|
+
end
|
473
|
+
def put(ary)
|
474
|
+
@ary = ary
|
475
|
+
@length = val.length
|
476
|
+
return @ary
|
477
|
+
end
|
478
|
+
def put_att(key,val)
|
479
|
+
@attr[key]=val
|
480
|
+
end
|
481
|
+
alias :set_att :put_att
|
482
|
+
def att(key)
|
483
|
+
@attr[key]
|
484
|
+
end
|
485
|
+
def att_names
|
486
|
+
@attr.keys
|
487
|
+
end
|
488
|
+
def inspect
|
489
|
+
"GribDim: #{name} length=#{length}"
|
490
|
+
end
|
491
|
+
end # class GribDim
|
492
|
+
|
493
|
+
end # module NumRu
|
494
|
+
|
495
|
+
|
496
|
+
|
497
|
+
|
498
|
+
|
499
|
+
#####################################################
|
500
|
+
if $0 == __FILE__
|
501
|
+
|
502
|
+
include NumRu
|
503
|
+
|
504
|
+
if ARGV.length>0
|
505
|
+
infname = ARGV.shift
|
506
|
+
else
|
507
|
+
infname = "../../../testdata/T.jan.grib"
|
508
|
+
end
|
509
|
+
|
510
|
+
|
511
|
+
Grib.is_a_Grib?(infname) || raise("file is not a Grib dataset")
|
512
|
+
p grib = Grib.open(infname)
|
513
|
+
|
514
|
+
|
515
|
+
|
516
|
+
print "\nVars\n"
|
517
|
+
grib.var_names.each{|vn|
|
518
|
+
p v = grib.var(vn)
|
519
|
+
p v.dim_names
|
520
|
+
v.dim_names.each{|dn| p dn; p v.dim(dn).get }
|
521
|
+
p v.shape
|
522
|
+
v.att_names.each{|an| print an, " => ", v.att(an), "\n" }
|
523
|
+
puts "\n"
|
524
|
+
p v.val
|
525
|
+
}
|
526
|
+
|
527
|
+
|
528
|
+
end
|
data/rb-grib.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "numru/grib/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rb-grib"
|
7
|
+
s.version = NumRu::Grib::VERSION
|
8
|
+
s.authors = ["Seiya Nishizawa"]
|
9
|
+
s.email = ["seiya@gfd-dennou.org"]
|
10
|
+
s.homepage = "http://ruby.gfd-dennu.org/products/rb-grib/"
|
11
|
+
s.summary = %q{Ruby class library to hanlde GRIB file}
|
12
|
+
s.description = %q{This class library enable you to handle GRIB file.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "rb-grib"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.extensions << "ext/extconf.rb"
|
21
|
+
|
22
|
+
# specify any dependencies here; for example:
|
23
|
+
# s.add_development_dependency "rspec"
|
24
|
+
# s.add_runtime_dependency "rest-client"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rb-grib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Seiya Nishizawa
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-29 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: This class library enable you to handle GRIB file.
|
22
|
+
email:
|
23
|
+
- seiya@gfd-dennou.org
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions:
|
27
|
+
- ext/extconf.rb
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- Gemfile
|
33
|
+
- LICENSE.txt
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- ext/extconf.rb
|
37
|
+
- ext/grib.c
|
38
|
+
- lib/numru/grib.rb
|
39
|
+
- lib/numru/grib/grib.rb
|
40
|
+
- lib/numru/grib/version.rb
|
41
|
+
- rb-grib.gemspec
|
42
|
+
homepage: http://ruby.gfd-dennu.org/products/rb-grib/
|
43
|
+
licenses: []
|
44
|
+
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
hash: 3
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project: rb-grib
|
71
|
+
rubygems_version: 1.8.10
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Ruby class library to hanlde GRIB file
|
75
|
+
test_files: []
|
76
|
+
|