rb-grib 0.1.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.
- 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
|
+
|