ruby-grads 1.0.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.
- checksums.yaml +7 -0
- data/README.md +31 -0
- data/extconf.rb +6 -0
- data/lib/grads/command.rb +751 -0
- data/lib/grads/gridded.rb +709 -0
- data/lib/grads/lib/colorbar.rb +192 -0
- data/lib/grads/lib/makecpt.rb +180 -0
- data/lib/grads/lib/save_image.rb +26 -0
- data/lib/grads/lib/xcbar_with_ccols.rb +32 -0
- data/lib/grads.rb +11 -0
- data/ruby-grads.gemspec +23 -0
- data/test/gradsdraw.rb +12 -0
- data/test/test.rb +41 -0
- metadata +54 -0
@@ -0,0 +1,751 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
require "open3"
|
3
|
+
require "date"
|
4
|
+
require "carray"
|
5
|
+
|
6
|
+
class GrADS::Command
|
7
|
+
|
8
|
+
class Expression
|
9
|
+
def initialize (expr)
|
10
|
+
@expr = expr
|
11
|
+
end
|
12
|
+
def to_s
|
13
|
+
return @expr
|
14
|
+
end
|
15
|
+
def paren
|
16
|
+
return ["(",@expr,")"].join
|
17
|
+
end
|
18
|
+
alias to_str to_s
|
19
|
+
def -@
|
20
|
+
return Expression.new(["-", self.paren].join)
|
21
|
+
end
|
22
|
+
def +@
|
23
|
+
return Expression.new(["+", self.paren].join)
|
24
|
+
end
|
25
|
+
def + (other)
|
26
|
+
case other
|
27
|
+
when Expression
|
28
|
+
return Expression.new([self.paren,"+",other.paren].join)
|
29
|
+
else
|
30
|
+
return Expression.new([self.paren,"+",other.to_s].join)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def - (other)
|
34
|
+
case other
|
35
|
+
when Expression
|
36
|
+
return Expression.new([self.paren,"-",other.paren].join)
|
37
|
+
else
|
38
|
+
return Expression.new([self.paren,"-",other.to_s].join)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
def / (other)
|
42
|
+
case other
|
43
|
+
when Expression
|
44
|
+
return Expression.new([self.paren,"/",other.paren].join)
|
45
|
+
else
|
46
|
+
return Expression.new([self.paren,"/",other.to_s].join)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def * (other)
|
50
|
+
case other
|
51
|
+
when Expression
|
52
|
+
return Expression.new([self.paren,"*",other.paren].join)
|
53
|
+
else
|
54
|
+
return Expression.new([self.paren,"*",other.to_s].join)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
def method_missing (id, *argv)
|
58
|
+
if argv.size > 0
|
59
|
+
return Expression.new(format("#{id}(%s,%s)", @expr, argv.join(",")))
|
60
|
+
else
|
61
|
+
return Expression.new(format("#{id}(%s)", @expr))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Variable < Expression
|
67
|
+
def initialize (file_id, name)
|
68
|
+
if file_id
|
69
|
+
@expr = [name,".",file_id].join("")
|
70
|
+
else
|
71
|
+
@expr = name.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
def to_s
|
75
|
+
return @expr
|
76
|
+
end
|
77
|
+
alias to_str to_s
|
78
|
+
def [] (hash)
|
79
|
+
spec = ["(",hash.map{ |k,v| [k,"=",v].join("") }.join(","),")"].join("")
|
80
|
+
return Expression.new([@expr,spec].join(""))
|
81
|
+
end
|
82
|
+
def method_missing (id, *argv)
|
83
|
+
if argv.size == 0
|
84
|
+
return Expression.new(format("#{id}(%s)", @expr))
|
85
|
+
else
|
86
|
+
return Expression.new(format("#{id}(%s,%s)", @expr, argv.join(",")))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class DataHandler
|
92
|
+
def initialize (file_id)
|
93
|
+
@file_id = file_id
|
94
|
+
end
|
95
|
+
attr_reader :file_id
|
96
|
+
def var (name)
|
97
|
+
return Variable.new(@file_id, name)
|
98
|
+
end
|
99
|
+
def method_missing (id, *argv)
|
100
|
+
if argv.empty?
|
101
|
+
return Variable.new(@file_id, id.to_s)
|
102
|
+
else
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize (*argv, &block)
|
109
|
+
if argv.last.is_a?(Hash)
|
110
|
+
options = argv.pop
|
111
|
+
else
|
112
|
+
options = {}
|
113
|
+
end
|
114
|
+
if argv.first
|
115
|
+
grads_command = argv.first
|
116
|
+
else
|
117
|
+
grads_command = "grads"
|
118
|
+
end
|
119
|
+
if options[:batch]
|
120
|
+
grads_command = grads_command + " -b"
|
121
|
+
end
|
122
|
+
if options[:portrait]
|
123
|
+
grads_command += " -p "
|
124
|
+
elsif options[:landscape]
|
125
|
+
grads_command += " -l "
|
126
|
+
else
|
127
|
+
grads_command += " -l "
|
128
|
+
end
|
129
|
+
begin
|
130
|
+
@io, @stdout, @stderr = Open3.popen3(grads_command)
|
131
|
+
rescue NotImplementedError
|
132
|
+
raise NotImplementedError, "system dosen't support Open3.popen3"
|
133
|
+
end
|
134
|
+
@debug = false
|
135
|
+
@log = ""
|
136
|
+
@imported = []
|
137
|
+
@echoback = false
|
138
|
+
@listen = Thread.start {
|
139
|
+
Thread.abort_on_exception = true
|
140
|
+
begin
|
141
|
+
while line = @stderr.gets ### read(1024)
|
142
|
+
STDERR << line
|
143
|
+
STDERR.flush
|
144
|
+
end
|
145
|
+
rescue IOError ### @stdout may externally closed
|
146
|
+
end
|
147
|
+
}
|
148
|
+
@io.puts "ECHOBACK_TEST_FOR_RUBY_GRADS"
|
149
|
+
while @stdout.gets !~ /Unknown command: ECHOBACK_TEST_FOR_RUBY_GRADS/
|
150
|
+
end
|
151
|
+
@io.puts "ECHOBACK_TEST_FOR_RUBY_GRADS"
|
152
|
+
if @stdout.gets =~ /ga-> ECHOBACK_TEST_FOR_RUBY_GRADS/
|
153
|
+
@echoback = true
|
154
|
+
@stdout.gets
|
155
|
+
else
|
156
|
+
@echoback = false
|
157
|
+
end
|
158
|
+
put "set grads off"
|
159
|
+
put "set timelab off"
|
160
|
+
if block_given?
|
161
|
+
begin
|
162
|
+
case block.arity
|
163
|
+
when 1
|
164
|
+
yield(self)
|
165
|
+
when -1, 0
|
166
|
+
instance_eval(&block)
|
167
|
+
else
|
168
|
+
raise "invalid # of block parameters"
|
169
|
+
end
|
170
|
+
ensure
|
171
|
+
self.quit
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
attr_reader :log
|
177
|
+
|
178
|
+
def method_missing (id, *argv)
|
179
|
+
return id, *argv
|
180
|
+
end
|
181
|
+
|
182
|
+
def quit
|
183
|
+
put("quit")
|
184
|
+
@io.close
|
185
|
+
@listen.join
|
186
|
+
@stdout.close
|
187
|
+
@stderr.close
|
188
|
+
end
|
189
|
+
|
190
|
+
alias exit quit
|
191
|
+
|
192
|
+
def put (*args)
|
193
|
+
command = args.join("\n")
|
194
|
+
@log << command << "\n"
|
195
|
+
if @debug
|
196
|
+
STDERR.puts "ga-> " + command
|
197
|
+
end
|
198
|
+
thread = Thread.start {
|
199
|
+
begin
|
200
|
+
size = command.size
|
201
|
+
s = 0
|
202
|
+
while s < size
|
203
|
+
s += @io.write(command[s, 1024])
|
204
|
+
end
|
205
|
+
@io.puts
|
206
|
+
@io.puts "SIGNAL_FOR_RUBY_GRADS"
|
207
|
+
@io.flush
|
208
|
+
rescue Errno::EPIPE
|
209
|
+
end
|
210
|
+
}
|
211
|
+
output = ""
|
212
|
+
while line = @stdout.gets
|
213
|
+
if @echoback and line =~ /^ga->\s+/
|
214
|
+
next
|
215
|
+
else
|
216
|
+
line.sub!(/^ga->\s+/,'')
|
217
|
+
end
|
218
|
+
case line
|
219
|
+
when /SIGNAL_FOR_RUBY_GRADS/
|
220
|
+
STDERR.print(output) if @debug and not output.empty?
|
221
|
+
return output.chomp
|
222
|
+
when /^(\w+) error: (.*?) /
|
223
|
+
output << line
|
224
|
+
STDERR.print output
|
225
|
+
raise "GRADS Error"
|
226
|
+
else
|
227
|
+
output << line
|
228
|
+
end
|
229
|
+
end
|
230
|
+
ensure
|
231
|
+
thread.join
|
232
|
+
end
|
233
|
+
|
234
|
+
def debug_on
|
235
|
+
@debug = true
|
236
|
+
end
|
237
|
+
|
238
|
+
def debug_off
|
239
|
+
@debug = false
|
240
|
+
end
|
241
|
+
|
242
|
+
def sublin (text, n)
|
243
|
+
return text.split(/\n/)[n-1]
|
244
|
+
end
|
245
|
+
|
246
|
+
def subwrd (text, n)
|
247
|
+
wrd = text.strip.split(/\s*\n\s*|\s+/)[n-1]
|
248
|
+
return wrd ? wrd.strip : ""
|
249
|
+
end
|
250
|
+
|
251
|
+
def open (*argv)
|
252
|
+
text = put "open " + argv.join(" ")
|
253
|
+
file_id = nil
|
254
|
+
text.each_line do |line|
|
255
|
+
if line =~ /is open as file/
|
256
|
+
file_id = subwrd(line, 8).to_i
|
257
|
+
break
|
258
|
+
end
|
259
|
+
end
|
260
|
+
if file_id
|
261
|
+
return DataHandler.new(file_id)
|
262
|
+
else
|
263
|
+
raise "failed to open file #{argv.first}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def close (dh)
|
268
|
+
file_id = dh.file_id
|
269
|
+
put "close #{file_id}"
|
270
|
+
end
|
271
|
+
|
272
|
+
def xdfopen (*argv)
|
273
|
+
text = put "xdfopen " + argv.join(" ")
|
274
|
+
file_id = nil
|
275
|
+
text.each_line do |line|
|
276
|
+
if line =~ /is open as file/
|
277
|
+
file_id = subwrd(line, 8).to_i
|
278
|
+
break
|
279
|
+
end
|
280
|
+
end
|
281
|
+
if file_id
|
282
|
+
return DataHandler.new(file_id)
|
283
|
+
else
|
284
|
+
raise "failed to open file #{argv.first}"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def sdfopen (*argv)
|
289
|
+
text = put "sdfopen " + argv.join(" ")
|
290
|
+
file_id = nil
|
291
|
+
text.each_line do |line|
|
292
|
+
if line =~ /is open as file/
|
293
|
+
file_id = subwrd(line, 8).to_i
|
294
|
+
break
|
295
|
+
end
|
296
|
+
end
|
297
|
+
if file_id
|
298
|
+
return DataHandler.new(file_id)
|
299
|
+
else
|
300
|
+
raise "failed to open file #{argv.first}"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def scan (ctltext)
|
305
|
+
io = Tempfile.open("CA_GrADS_", ".")
|
306
|
+
io.write ctltext
|
307
|
+
io.flush
|
308
|
+
return open(io.path)
|
309
|
+
ensure
|
310
|
+
io.close
|
311
|
+
end
|
312
|
+
|
313
|
+
def xdfscan (ctltext)
|
314
|
+
io = Tempfile.open("CA_GrADS_", ".")
|
315
|
+
io.write ctltext
|
316
|
+
io.flush
|
317
|
+
return xdfopen(io.path)
|
318
|
+
ensure
|
319
|
+
io.close
|
320
|
+
end
|
321
|
+
|
322
|
+
def exec (name, *argv)
|
323
|
+
put "exec #{name} " + argv.flatten.join(" ")
|
324
|
+
end
|
325
|
+
|
326
|
+
def exec_string (definition, *argv)
|
327
|
+
io = Tempfile.open("CA_GrADS_", ".")
|
328
|
+
io.write definition
|
329
|
+
io.puts
|
330
|
+
io.flush
|
331
|
+
return exec(io.path, *argv)
|
332
|
+
ensure
|
333
|
+
io.close
|
334
|
+
end
|
335
|
+
|
336
|
+
def script (name, definition)
|
337
|
+
io = Tempfile.new("CA_GrADS_", ".")
|
338
|
+
io.write(definition)
|
339
|
+
io.flush
|
340
|
+
instance_eval %{
|
341
|
+
def #{name} (*args)
|
342
|
+
run "#{io.path}", *args
|
343
|
+
end
|
344
|
+
}
|
345
|
+
end
|
346
|
+
|
347
|
+
def set (*argv)
|
348
|
+
put "set " + argv.flatten.join(" ")
|
349
|
+
end
|
350
|
+
|
351
|
+
def display (*argv)
|
352
|
+
if argv.first.is_a?(Array)
|
353
|
+
put "display " + argv.first.map{|v| "("+v.to_s+")" }.join(";")
|
354
|
+
else
|
355
|
+
put "display " + argv.join(" ")
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def define (name, expr)
|
360
|
+
put "define #{name} = " + expr
|
361
|
+
return Variable.new(nil, name)
|
362
|
+
end
|
363
|
+
|
364
|
+
def eval (expr)
|
365
|
+
put expr.to_s
|
366
|
+
end
|
367
|
+
|
368
|
+
def enable (id, *argv)
|
369
|
+
case id.to_s
|
370
|
+
when "print"
|
371
|
+
begin
|
372
|
+
put "enable print " + argv.join(" ")
|
373
|
+
yield
|
374
|
+
ensure
|
375
|
+
put "disable print"
|
376
|
+
end
|
377
|
+
else
|
378
|
+
put "enable #{id} " + argv.join(" ")
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def draw (*argv)
|
383
|
+
put "draw " + argv.flatten.join(" ")
|
384
|
+
end
|
385
|
+
|
386
|
+
def redraw (*argv)
|
387
|
+
put "redraw " + argv.flatten.join(" ")
|
388
|
+
end
|
389
|
+
|
390
|
+
[
|
391
|
+
"buffrscan",
|
392
|
+
"collect",
|
393
|
+
"disable",
|
394
|
+
"flush",
|
395
|
+
"modify",
|
396
|
+
"outxwd",
|
397
|
+
"print",
|
398
|
+
"printim",
|
399
|
+
"gxprint",
|
400
|
+
"query",
|
401
|
+
"quit",
|
402
|
+
"reinit",
|
403
|
+
"reset",
|
404
|
+
"run",
|
405
|
+
"sdfwrite",
|
406
|
+
"swap",
|
407
|
+
"undefine",
|
408
|
+
].each do |name|
|
409
|
+
class_eval %{
|
410
|
+
def #{name} (*argv)
|
411
|
+
put "#{name} " + argv.join(" ")
|
412
|
+
end
|
413
|
+
}
|
414
|
+
end
|
415
|
+
|
416
|
+
def clear (*argv)
|
417
|
+
@ccols = nil
|
418
|
+
@clevs = nil
|
419
|
+
put "clear " + argv.join(" ")
|
420
|
+
end
|
421
|
+
|
422
|
+
alias d display
|
423
|
+
alias c clear
|
424
|
+
alias q query
|
425
|
+
|
426
|
+
def set_time (*argv)
|
427
|
+
list = []
|
428
|
+
argv.each do |time|
|
429
|
+
timestr = nil
|
430
|
+
case time
|
431
|
+
when DateTime, Time
|
432
|
+
timestr = time.strftime("%H:%Mz%d%b%Y")
|
433
|
+
when Date
|
434
|
+
timestr = time.strftime("%d%b%Y")
|
435
|
+
when String
|
436
|
+
timestr = time
|
437
|
+
else
|
438
|
+
raise "unknown time variable #{time.inspect}"
|
439
|
+
end
|
440
|
+
list << timestr
|
441
|
+
end
|
442
|
+
set :time, *list
|
443
|
+
end
|
444
|
+
|
445
|
+
def get_time
|
446
|
+
list = query("time").split(/\s+/)
|
447
|
+
if list[2] == list[4]
|
448
|
+
return DateTime.parse(list[2].sub(/Z/," "))
|
449
|
+
else
|
450
|
+
return DateTime.parse(list[2].sub(/Z/," "))..DateTime.parse(list[4].sub(/Z/," "))
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
def get_time_start
|
455
|
+
list = query("time").split(/\s+/)
|
456
|
+
return DateTime.parse(list[2].sub(/Z/," "))
|
457
|
+
end
|
458
|
+
|
459
|
+
def get_time_end
|
460
|
+
list = query("time").split(/\s+/)
|
461
|
+
return DateTime.parse(list[4].sub(/Z/," "))
|
462
|
+
end
|
463
|
+
|
464
|
+
def get_level
|
465
|
+
return subwrd(sublin(query("dims"),4),6).to_f
|
466
|
+
end
|
467
|
+
|
468
|
+
def get_value (*argv)
|
469
|
+
var = argv.shift
|
470
|
+
if argv.empty?
|
471
|
+
list = query(:defval, var, 0, 0).split(/\s+/)
|
472
|
+
else
|
473
|
+
list = query(:defval, var, *argv).split(/\s+/)
|
474
|
+
end
|
475
|
+
return list[2].to_f
|
476
|
+
end
|
477
|
+
|
478
|
+
def get_mouse_click (trans = nil)
|
479
|
+
list = query("pos").split(/\s+/)
|
480
|
+
button = list[4].to_i
|
481
|
+
x, y = list[2].to_f, list[3].to_f
|
482
|
+
if trans
|
483
|
+
list = query(trans, x, y).split(/\s+/)
|
484
|
+
x, y = list[2].to_f, list[5].to_f
|
485
|
+
end
|
486
|
+
return x, y, button
|
487
|
+
end
|
488
|
+
|
489
|
+
def transform (kind, v1, v2)
|
490
|
+
result = query(kind, v1, v2)
|
491
|
+
r1 = subwrd(result, 3)
|
492
|
+
r2 = subwrd(result, 6)
|
493
|
+
return r1, r2
|
494
|
+
end
|
495
|
+
|
496
|
+
def w2xy (lat, lon)
|
497
|
+
return transform(:w2xy, lat, lon)
|
498
|
+
end
|
499
|
+
|
500
|
+
def w2gr (lat, lon)
|
501
|
+
return transform(:w2gr, lat, lon)
|
502
|
+
end
|
503
|
+
|
504
|
+
def gr2w (fi, fj)
|
505
|
+
return transform(:gr2w, fi, fj)
|
506
|
+
end
|
507
|
+
|
508
|
+
def gr2xy (fi, fj)
|
509
|
+
return transform(:gr2xy, fi, fj)
|
510
|
+
end
|
511
|
+
|
512
|
+
def xy2w (x, y)
|
513
|
+
return transform(:xy2w, x, y)
|
514
|
+
end
|
515
|
+
|
516
|
+
def xy2gr (x, y)
|
517
|
+
return transform(:xy2gr, x, y)
|
518
|
+
end
|
519
|
+
|
520
|
+
def set_clevs (*argv)
|
521
|
+
@clevs = argv
|
522
|
+
set :clevs, *argv
|
523
|
+
end
|
524
|
+
|
525
|
+
def set_ccols (*argv)
|
526
|
+
@ccols = argv
|
527
|
+
set :ccols, *argv
|
528
|
+
end
|
529
|
+
|
530
|
+
def import (*args)
|
531
|
+
args.each do |name|
|
532
|
+
if @imported.include?(name)
|
533
|
+
next
|
534
|
+
end
|
535
|
+
self.class.module_eval %{
|
536
|
+
def #{name} (*argv)
|
537
|
+
put "#{name} " + argv.join(" ")
|
538
|
+
end
|
539
|
+
}
|
540
|
+
@imported.push name
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def imported? (arg)
|
545
|
+
return @imported.include?(arg)
|
546
|
+
end
|
547
|
+
|
548
|
+
def pause
|
549
|
+
get_mouse_click
|
550
|
+
end
|
551
|
+
|
552
|
+
def template2d (sd, *args, &block)
|
553
|
+
return __template__(2, sd, *args, &block)
|
554
|
+
end
|
555
|
+
|
556
|
+
def template3d (sd, *args, &block)
|
557
|
+
return __template__(3, sd, *args, &block)
|
558
|
+
end
|
559
|
+
|
560
|
+
def __template__ (d, sd, *args, &block)
|
561
|
+
if args.last.is_a?(Hash)
|
562
|
+
opts = args.pop
|
563
|
+
else
|
564
|
+
opts = {}
|
565
|
+
end
|
566
|
+
args = args.map{|v| CA_FLOAT(v) }
|
567
|
+
dataio = Tempfile.open("CA_GrADS_", ".")
|
568
|
+
dataname = dataio.path
|
569
|
+
datactl = dataname + ".ctl"
|
570
|
+
if sd
|
571
|
+
result = q :file, sd.file_id
|
572
|
+
ctlfile = subwrd(sublin(result, 2), 2)
|
573
|
+
ctl = GrADS::Gridded.new(ctlfile)
|
574
|
+
else
|
575
|
+
ref = args.first
|
576
|
+
ctl = GrADS::Gridded::Writer.new
|
577
|
+
case d
|
578
|
+
when 2
|
579
|
+
if ref.rank == 2
|
580
|
+
ctl.define {
|
581
|
+
tdef "1 linear 0z01jan2000 1dy"
|
582
|
+
zdef "1 linear 1 1"
|
583
|
+
ydef ref.dim0, "linear 1 1"
|
584
|
+
xdef ref.dim1, "linear 1 1"
|
585
|
+
}
|
586
|
+
else
|
587
|
+
ctl.define {
|
588
|
+
tdef ref.dim0, "linear 0z01jan2000 1dy"
|
589
|
+
zdef "1 linear 1 1"
|
590
|
+
ydef ref.dim1, "linear 1 1"
|
591
|
+
xdef ref.dim2, "linear 1 1"
|
592
|
+
}
|
593
|
+
end
|
594
|
+
when 3
|
595
|
+
if ref.rank == 3
|
596
|
+
ctl.define {
|
597
|
+
tdef "1 linear 0z01jan2000 1dy"
|
598
|
+
zdef ref.dim0, "linear 1 1"
|
599
|
+
ydef ref.dim1, "linear 1 1"
|
600
|
+
xdef ref.dim2, "linear 1 1"
|
601
|
+
}
|
602
|
+
else
|
603
|
+
ctl.define {
|
604
|
+
tdef ref.dim0, "linear 0z01jan2000 1dy"
|
605
|
+
zdef ref.dim1, "linear 1 1"
|
606
|
+
ydef ref.dim2, "linear 1 1"
|
607
|
+
xdef ref.dim3, "linear 1 1"
|
608
|
+
}
|
609
|
+
end
|
610
|
+
end
|
611
|
+
end
|
612
|
+
ctl.define {
|
613
|
+
if opts[:undef]
|
614
|
+
undef! opts[:undef]
|
615
|
+
else
|
616
|
+
undef! 1e30
|
617
|
+
end
|
618
|
+
}
|
619
|
+
if block
|
620
|
+
ctl.define(&block)
|
621
|
+
end
|
622
|
+
begin
|
623
|
+
names = []
|
624
|
+
ctl.template(datactl) do
|
625
|
+
dset dataname
|
626
|
+
args.each_with_index do |arg, i|
|
627
|
+
names << ( name = "tmpvar#{i}" )
|
628
|
+
case d
|
629
|
+
when 2
|
630
|
+
var2d(name, arg)
|
631
|
+
when 3
|
632
|
+
var3d(name, arg)
|
633
|
+
end
|
634
|
+
end
|
635
|
+
end
|
636
|
+
ss = open(datactl)
|
637
|
+
vars = []
|
638
|
+
names.each do |name|
|
639
|
+
vars << define(name, ss.send(name))
|
640
|
+
end
|
641
|
+
return vars
|
642
|
+
ensure
|
643
|
+
dataio.close
|
644
|
+
File.unlink(datactl)
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
begin
|
649
|
+
require "netcdflib"
|
650
|
+
def get_var (expr)
|
651
|
+
@var_id ||= 0
|
652
|
+
@var_id += 1
|
653
|
+
filename = "CA_GRADS_#{$$}_#{@var_id}.nc"
|
654
|
+
begin
|
655
|
+
define :grdvar, expr
|
656
|
+
set :sdfwrite, filename
|
657
|
+
sdfwrite :grdvar
|
658
|
+
nc_id = NC.open(filename, NC::NC_NOWRITE)
|
659
|
+
var_id = NC.inq_varid(nc_id, "grdvar")
|
660
|
+
rank = NC.inq_varndims(nc_id, var_id)
|
661
|
+
dim = Array.new(rank)
|
662
|
+
axis = Array.new(rank)
|
663
|
+
dim_ids = NC.inq_vardimid(nc_id, var_id)
|
664
|
+
dim_ids.each_with_index do |dim_id, i|
|
665
|
+
dim[i] = NC.inq_dimlen(nc_id,dim_id)
|
666
|
+
name = NC.inq_dimname(nc_id,dim_id)
|
667
|
+
axis_id = NC.inq_varid(nc_id,name)
|
668
|
+
axis[i] = CArray.double(dim[i])
|
669
|
+
NC.get_var(nc_id,axis_id,axis[i])
|
670
|
+
if name == "time"
|
671
|
+
NC.get_att(nc_id, axis_id, "units", str = "")
|
672
|
+
units, inittime = *str.split(/\s*since\s*/)
|
673
|
+
time0 = DateTime.parse(inittime)
|
674
|
+
case units
|
675
|
+
when "minutes"
|
676
|
+
axis[i] = axis[i].convert(:object) {|x| time0 + x.to_i * 1.quo(1440) }
|
677
|
+
else
|
678
|
+
raise "unknown time minutes"
|
679
|
+
end
|
680
|
+
end
|
681
|
+
end
|
682
|
+
data = CArray.double(*dim)
|
683
|
+
NC.get_var(nc_id, var_id, data)
|
684
|
+
miss = CScalar.double
|
685
|
+
NC.get_att(nc_id, var_id, "missing_value", miss)
|
686
|
+
NC.close(nc_id)
|
687
|
+
data[:eq,miss] = UNDEF
|
688
|
+
#ensure
|
689
|
+
File.unlink(filename)
|
690
|
+
end
|
691
|
+
return data, axis.reverse
|
692
|
+
end
|
693
|
+
rescue LoadError
|
694
|
+
begin
|
695
|
+
require "numru/netcdf"
|
696
|
+
def get_var (expr)
|
697
|
+
@var_id ||= 0
|
698
|
+
@var_id += 1
|
699
|
+
filename = "CA_GRADS_#{$$}_#{@var_id}.nc"
|
700
|
+
begin
|
701
|
+
define :grdvar, expr
|
702
|
+
set :sdfwrite, filename
|
703
|
+
sdfwrite :grdvar
|
704
|
+
nc = NumRu::NetCDF.open(filename)
|
705
|
+
var = nc.var("grdvar")
|
706
|
+
axis = []
|
707
|
+
var.dim_names.each_with_index do |name,i|
|
708
|
+
axis[i] = nc.var(name).get.ca
|
709
|
+
if name == "time"
|
710
|
+
str = nc.var(name).att("units").get
|
711
|
+
units, inittime = *str.split(/\s*since\s*/)
|
712
|
+
time0 = DateTime.parse(inittime)
|
713
|
+
case units
|
714
|
+
when "minutes"
|
715
|
+
axis[i] = axis[i].convert(:object) {|x| time0 + x.to_i * 1.quo(1440) }
|
716
|
+
else
|
717
|
+
raise "unknown time minutes"
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end
|
721
|
+
miss = var.att("missing_value").get
|
722
|
+
data = var.get.ca
|
723
|
+
data[:eq,miss] = UNDEF
|
724
|
+
ensure
|
725
|
+
File.unlink(filename)
|
726
|
+
end
|
727
|
+
return data, axis.reverse
|
728
|
+
end
|
729
|
+
rescue LoadError
|
730
|
+
end
|
731
|
+
end
|
732
|
+
|
733
|
+
end
|
734
|
+
|
735
|
+
def GrADS.start (*argv, &block)
|
736
|
+
return GrADS::Command.new(*argv, &block)
|
737
|
+
end
|
738
|
+
|
739
|
+
def GrADS.script (name, definition)
|
740
|
+
io = Tempfile.new("CA_GrADS_", ".")
|
741
|
+
io.write(definition)
|
742
|
+
io.flush
|
743
|
+
GrADS::Command.class_eval %{
|
744
|
+
def #{name} (*args)
|
745
|
+
run "#{io.path}", *args
|
746
|
+
end
|
747
|
+
}
|
748
|
+
end
|
749
|
+
|
750
|
+
|
751
|
+
|