ruby-grads 1.0.0 → 1.0.7
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 +4 -4
- data/README.md +67 -1
- data/Rakefile +14 -0
- data/bin/ncdef2ctl +107 -0
- data/lib/grads/binary.rb +735 -0
- data/lib/grads/command.rb +428 -11
- data/lib/grads/gridded.rb +83 -14
- data/lib/grads/lib/axis_xtime.rb +217 -0
- data/lib/grads/lib/makecpt.rb +24 -54
- data/lib/grads.rb +1 -0
- data/ruby-grads.gemspec +3 -3
- data/ruby-grads.gemspec~ +23 -0
- metadata +10 -5
data/lib/grads/command.rb
CHANGED
@@ -75,8 +75,15 @@ class GrADS::Command
|
|
75
75
|
return @expr
|
76
76
|
end
|
77
77
|
alias to_str to_s
|
78
|
-
def [] (
|
79
|
-
|
78
|
+
def [] (expr)
|
79
|
+
case expr
|
80
|
+
when Hash
|
81
|
+
spec = ["(",hash.map{ |k,v| [k,"=",v].join("") }.join(","),")"].join("")
|
82
|
+
when String
|
83
|
+
spec = "("+expr+")"
|
84
|
+
else
|
85
|
+
raise "unknown expression"
|
86
|
+
end
|
80
87
|
return Expression.new([@expr,spec].join(""))
|
81
88
|
end
|
82
89
|
def method_missing (id, *argv)
|
@@ -176,7 +183,11 @@ class GrADS::Command
|
|
176
183
|
attr_reader :log
|
177
184
|
|
178
185
|
def method_missing (id, *argv)
|
179
|
-
|
186
|
+
if argv.empty?
|
187
|
+
return id
|
188
|
+
else
|
189
|
+
super
|
190
|
+
end
|
180
191
|
end
|
181
192
|
|
182
193
|
def quit
|
@@ -402,7 +413,6 @@ class GrADS::Command
|
|
402
413
|
"reinit",
|
403
414
|
"reset",
|
404
415
|
"run",
|
405
|
-
"sdfwrite",
|
406
416
|
"swap",
|
407
417
|
"undefine",
|
408
418
|
].each do |name|
|
@@ -413,9 +423,21 @@ class GrADS::Command
|
|
413
423
|
}
|
414
424
|
end
|
415
425
|
|
426
|
+
[
|
427
|
+
"sdfwrite",
|
428
|
+
].each do |name|
|
429
|
+
class_eval %{
|
430
|
+
def #{name} (*argv)
|
431
|
+
if argv.empty?
|
432
|
+
return :#{name}
|
433
|
+
else
|
434
|
+
put "#{name} " + argv.join(" ")
|
435
|
+
end
|
436
|
+
end
|
437
|
+
}
|
438
|
+
end
|
439
|
+
|
416
440
|
def clear (*argv)
|
417
|
-
@ccols = nil
|
418
|
-
@clevs = nil
|
419
441
|
put "clear " + argv.join(" ")
|
420
442
|
end
|
421
443
|
|
@@ -518,13 +540,20 @@ class GrADS::Command
|
|
518
540
|
end
|
519
541
|
|
520
542
|
def set_clevs (*argv)
|
521
|
-
@clevs = argv
|
522
543
|
set :clevs, *argv
|
523
544
|
end
|
524
545
|
|
525
546
|
def set_ccols (*argv)
|
526
|
-
|
527
|
-
|
547
|
+
list = []
|
548
|
+
argv.each do |arg|
|
549
|
+
case arg
|
550
|
+
when RGB
|
551
|
+
list << set_rgb(arg)
|
552
|
+
else
|
553
|
+
list << arg
|
554
|
+
end
|
555
|
+
end
|
556
|
+
set :ccols, *list
|
528
557
|
end
|
529
558
|
|
530
559
|
def import (*args)
|
@@ -646,7 +675,7 @@ class GrADS::Command
|
|
646
675
|
end
|
647
676
|
|
648
677
|
begin
|
649
|
-
require "
|
678
|
+
require "simple-netcdf"
|
650
679
|
def get_var (expr)
|
651
680
|
@var_id ||= 0
|
652
681
|
@var_id += 1
|
@@ -730,6 +759,395 @@ class GrADS::Command
|
|
730
759
|
end
|
731
760
|
end
|
732
761
|
|
762
|
+
class Area
|
763
|
+
|
764
|
+
def initialize (x1, x2, y1, y2)
|
765
|
+
@x1 = x1
|
766
|
+
@x2 = x2
|
767
|
+
@y1 = y1
|
768
|
+
@y2 = y2
|
769
|
+
end
|
770
|
+
|
771
|
+
attr_reader :x1, :x2, :y1, :y2
|
772
|
+
|
773
|
+
def w
|
774
|
+
return @x2 - @x1
|
775
|
+
end
|
776
|
+
|
777
|
+
def h
|
778
|
+
return @y2 - @y1
|
779
|
+
end
|
780
|
+
|
781
|
+
def center
|
782
|
+
return @x1 + w/2
|
783
|
+
end
|
784
|
+
|
785
|
+
def mid
|
786
|
+
return @y1 + h/2
|
787
|
+
end
|
788
|
+
|
789
|
+
end
|
790
|
+
|
791
|
+
def len (str)
|
792
|
+
ans = query("string #{str}")
|
793
|
+
return subwrd(ans, 4).to_f
|
794
|
+
end
|
795
|
+
|
796
|
+
def parea (x1, x2, y1, y2)
|
797
|
+
set :parea, x1, x2, y1, y2
|
798
|
+
set :clip, x1, x2, y1, y2
|
799
|
+
yield Area.new(x1, x2, y1, y2)
|
800
|
+
end
|
801
|
+
|
802
|
+
def vpage (x1, x2, y1, y2)
|
803
|
+
set :vpage, x1, x2, y1, y2
|
804
|
+
yield Area.new(x1, x2, y1, y2)
|
805
|
+
end
|
806
|
+
|
807
|
+
def display_nothing (dummy)
|
808
|
+
ans = query("dims")
|
809
|
+
case ans.scan("varying").size
|
810
|
+
when 2
|
811
|
+
set :gxout, :contour
|
812
|
+
set :clevs, -9.99e99
|
813
|
+
set :ccolor, -1
|
814
|
+
set :clab, :off
|
815
|
+
set :cmark, 0
|
816
|
+
when 1
|
817
|
+
set :gxout, :line
|
818
|
+
set :line, -1
|
819
|
+
set :ylab, :off
|
820
|
+
set :vrange, -9.99e99, -9.99e98
|
821
|
+
end
|
822
|
+
if block_given?
|
823
|
+
yield
|
824
|
+
end
|
825
|
+
case dummy
|
826
|
+
when String
|
827
|
+
put "display #{dummy}"
|
828
|
+
else
|
829
|
+
display dummy
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
def axis_off
|
834
|
+
set :frame, :off
|
835
|
+
set :xlab, :off
|
836
|
+
set :ylab, :off
|
837
|
+
set :grid, :off
|
838
|
+
set :grads, :off
|
839
|
+
set :mpdraw, :off
|
840
|
+
end
|
841
|
+
|
842
|
+
def axis_on
|
843
|
+
set :frame, :on
|
844
|
+
set :xlab, :on
|
845
|
+
set :ylab, :on
|
846
|
+
set :grid, :on
|
847
|
+
set :grads, :on
|
848
|
+
set :mpdraw, :on
|
849
|
+
end
|
850
|
+
|
851
|
+
def plot (var, *args)
|
852
|
+
begin
|
853
|
+
axis_off
|
854
|
+
if block_given?
|
855
|
+
yield
|
856
|
+
end
|
857
|
+
set :gxout, *args
|
858
|
+
case var
|
859
|
+
when String
|
860
|
+
put "display #{var}"
|
861
|
+
else
|
862
|
+
display var
|
863
|
+
end
|
864
|
+
ensure
|
865
|
+
axis_on
|
866
|
+
end
|
867
|
+
end
|
868
|
+
|
869
|
+
def axis (dummy, &block)
|
870
|
+
begin
|
871
|
+
axis_on
|
872
|
+
display_nothing(dummy, &block)
|
873
|
+
ensure
|
874
|
+
axis_off
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
def draw_ylabel (text, area:, color: 1, just: "bc", thickness: 3, rot: 90, offset: "M", side: "l")
|
879
|
+
set :string, color, just, thickness, rot
|
880
|
+
case side
|
881
|
+
when "l"
|
882
|
+
draw :string, area.x1-len(offset), area.mid, text
|
883
|
+
when "r"
|
884
|
+
draw :string, area.x2+len(offset), area.mid, text
|
885
|
+
else
|
886
|
+
raise "invalid side sepecification"
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
890
|
+
def draw_xlabel (text, area:, color: 1, just: "bc", thickness: 3, rot: 0, offset: "M", side: "b")
|
891
|
+
set :string, color, just, thickness, rot
|
892
|
+
case side
|
893
|
+
when "b"
|
894
|
+
draw :string, area.center, area.y1-len(offset), text
|
895
|
+
when "t"
|
896
|
+
draw :string, area.center, area.y2+len(offset), text
|
897
|
+
else
|
898
|
+
raise "invalid side sepecification"
|
899
|
+
end
|
900
|
+
end
|
901
|
+
|
902
|
+
COLOR_TABLE = {
|
903
|
+
"background" => 0,
|
904
|
+
"foregraound" => 1,
|
905
|
+
"red" => 2,
|
906
|
+
"green" => 3,
|
907
|
+
"dark blue" => 4,
|
908
|
+
"light blue" => 5,
|
909
|
+
"magenta" => 6,
|
910
|
+
"yellow" => 7,
|
911
|
+
"orange" => 8,
|
912
|
+
"purple" => 9,
|
913
|
+
"yellow green" => 10,
|
914
|
+
"medium blue" => 11,
|
915
|
+
"dark yellow" => 12,
|
916
|
+
"aqua" => 13,
|
917
|
+
"dark purple" => 14,
|
918
|
+
"gray" => 15,
|
919
|
+
}
|
920
|
+
|
921
|
+
def COLOR (name)
|
922
|
+
if COLOR_TABLE.has_key?(name)
|
923
|
+
COLOR_TABLE[name]
|
924
|
+
else
|
925
|
+
-1
|
926
|
+
end
|
927
|
+
end
|
928
|
+
|
929
|
+
class LINE
|
930
|
+
|
931
|
+
def initialize (type = 1, color: 1, thickness: 3)
|
932
|
+
case type
|
933
|
+
when "","solid"
|
934
|
+
@type = 1
|
935
|
+
when "--", "long dash"
|
936
|
+
@type = 2
|
937
|
+
when "-", "short dash"
|
938
|
+
@type = 3
|
939
|
+
when "-- -", "long dash short dash"
|
940
|
+
@type = 4
|
941
|
+
when ".", "dotted"
|
942
|
+
@type = 5
|
943
|
+
when ". -", "dot dash"
|
944
|
+
@type = 6
|
945
|
+
when ". . -", "dot dot dash"
|
946
|
+
@type = 7
|
947
|
+
else
|
948
|
+
@type = type
|
949
|
+
end
|
950
|
+
@color = color
|
951
|
+
@thickness = thickness
|
952
|
+
end
|
953
|
+
|
954
|
+
attr_reader :type, :color
|
955
|
+
|
956
|
+
def to_a
|
957
|
+
return [@color, @type, @thickness]
|
958
|
+
end
|
959
|
+
|
960
|
+
end
|
961
|
+
|
962
|
+
class TILE
|
963
|
+
|
964
|
+
def self.reset
|
965
|
+
@@number = 0
|
966
|
+
end
|
967
|
+
|
968
|
+
def self.next_number
|
969
|
+
@@number += 1
|
970
|
+
if @@number > 2047
|
971
|
+
reset
|
972
|
+
end
|
973
|
+
return @@number
|
974
|
+
end
|
975
|
+
|
976
|
+
reset
|
977
|
+
|
978
|
+
def initialize (type, width: 6, height: nil, thickness: 3, color: 1, bgcolor: -1)
|
979
|
+
case type
|
980
|
+
when "."
|
981
|
+
@type = 2
|
982
|
+
when "\\"
|
983
|
+
@type = 3
|
984
|
+
when "/"
|
985
|
+
@type = 4
|
986
|
+
when "x"
|
987
|
+
@type = 5
|
988
|
+
when "|"
|
989
|
+
@type = 6
|
990
|
+
when "-"
|
991
|
+
@type = 7
|
992
|
+
when "#", "+"
|
993
|
+
@type = 8
|
994
|
+
else
|
995
|
+
@type = type
|
996
|
+
end
|
997
|
+
@width = width
|
998
|
+
@height = height || width
|
999
|
+
@thickness = thickness
|
1000
|
+
@color = color
|
1001
|
+
@bgcolor = bgcolor
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
attr_reader :type, :color
|
1005
|
+
|
1006
|
+
def to_a
|
1007
|
+
return [@type, @width, @height, @thickness, @color, @bgcolor]
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
class RGB
|
1013
|
+
|
1014
|
+
@@number = nil
|
1015
|
+
@@table = {}
|
1016
|
+
|
1017
|
+
def self.reset
|
1018
|
+
@@number = 100
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def self.next_number
|
1022
|
+
@@number += 1
|
1023
|
+
if @@number > 2047
|
1024
|
+
reset
|
1025
|
+
end
|
1026
|
+
return @@number
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
reset
|
1030
|
+
|
1031
|
+
def initialize (r, g, b, a=255)
|
1032
|
+
@r = r
|
1033
|
+
@g = g
|
1034
|
+
@b = b
|
1035
|
+
@a = a
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
attr_reader :r, :g, :b, :a
|
1039
|
+
|
1040
|
+
def to_s
|
1041
|
+
return format("%i %i %i %i", @r, @g, @b, @a)
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
def to_a
|
1045
|
+
return [@r, @g, @b, @a]
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
def % (alpha)
|
1049
|
+
if alpha >= 0 and alpha <= 1
|
1050
|
+
a = (@a*alpha).to_i
|
1051
|
+
else
|
1052
|
+
raise "invalid alpha value"
|
1053
|
+
end
|
1054
|
+
return RGB.new(@r, @g, @b, a)
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def * (scale)
|
1058
|
+
if scale >= 0 and scale <= 1
|
1059
|
+
return RGB.new((@r*scale).to_i, (@g*scale).to_i, (@b*scale).to_i, @a)
|
1060
|
+
else
|
1061
|
+
raise "invalid scale value"
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
|
1065
|
+
def / (scale)
|
1066
|
+
if scale >= 1
|
1067
|
+
return RGB.new((@r/scale).to_i, (@g/scale).to_i, (@b/scale).to_i, @a)
|
1068
|
+
else
|
1069
|
+
raise "invalid scale value"
|
1070
|
+
end
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
def + (other)
|
1074
|
+
r = [self.r, other.r].max
|
1075
|
+
g = [self.g, other.g].max
|
1076
|
+
b = [self.b, other.b].max
|
1077
|
+
a = [self.a, other.a].max
|
1078
|
+
return RGB.new(r,g,b,a)
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
def LINE (*argv)
|
1084
|
+
return LINE.new(*argv)
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
def TILE (*argv)
|
1088
|
+
return TILE.new(*argv)
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def RGB (*argv)
|
1092
|
+
case argv.size
|
1093
|
+
when 1
|
1094
|
+
return GrADS::Command::RGB_TABLE[argv[0]]
|
1095
|
+
else
|
1096
|
+
return GrADS::Command::RGB.new(*argv)
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
def self.RGB (*argv)
|
1101
|
+
case argv.size
|
1102
|
+
when 1
|
1103
|
+
return GrADS::Command::RGB_TABLE[argv[0]]
|
1104
|
+
else
|
1105
|
+
return GrADS::Command::RGB.new(*argv)
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
RGB_TABLE = {
|
1110
|
+
"red" => RGB(255,0,0),
|
1111
|
+
"green" => RGB(0,255,0),
|
1112
|
+
"blue" => RGB(0,0,255),
|
1113
|
+
}
|
1114
|
+
RGB_TABLE.update({
|
1115
|
+
"cyan" => RGB("green") + RGB("blue"),
|
1116
|
+
})
|
1117
|
+
|
1118
|
+
def set_line (obj)
|
1119
|
+
args = obj.to_a
|
1120
|
+
if obj.color.is_a?(RGB)
|
1121
|
+
args[0] = set_rgb(obj.color)
|
1122
|
+
end
|
1123
|
+
set :line, *args
|
1124
|
+
set :ccolor, args[0]
|
1125
|
+
set :cstyle, args[1]
|
1126
|
+
set :cthick, args[2]
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
def set_rgb (*argv)
|
1130
|
+
list = []
|
1131
|
+
argv.each do |obj|
|
1132
|
+
num = RGB.next_number
|
1133
|
+
case obj
|
1134
|
+
when TILE
|
1135
|
+
nt = TILE.next_number
|
1136
|
+
args = obj.to_a
|
1137
|
+
if obj.color.is_a?(RGB)
|
1138
|
+
c = set_rgb(obj.color)
|
1139
|
+
args[4] = c
|
1140
|
+
end
|
1141
|
+
set :tile, nt, *args.to_a
|
1142
|
+
set :rgb, num, :tile, nt
|
1143
|
+
when RGB
|
1144
|
+
set :rgb, num, *obj.to_a
|
1145
|
+
end
|
1146
|
+
list << num
|
1147
|
+
end
|
1148
|
+
return list
|
1149
|
+
end
|
1150
|
+
|
733
1151
|
end
|
734
1152
|
|
735
1153
|
def GrADS.start (*argv, &block)
|
@@ -748,4 +1166,3 @@ def GrADS.script (name, definition)
|
|
748
1166
|
end
|
749
1167
|
|
750
1168
|
|
751
|
-
|
data/lib/grads/gridded.rb
CHANGED
@@ -34,6 +34,16 @@
|
|
34
34
|
require "carray"
|
35
35
|
require "strscan"
|
36
36
|
|
37
|
+
begin
|
38
|
+
require "simple-proj"
|
39
|
+
require "simple-proj-carray"
|
40
|
+
rescue LoadError
|
41
|
+
begin
|
42
|
+
require "proj4r"
|
43
|
+
rescue LoadError
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
37
47
|
module GrADS
|
38
48
|
end
|
39
49
|
|
@@ -128,9 +138,10 @@ end
|
|
128
138
|
|
129
139
|
class GrADS::Gridded
|
130
140
|
|
131
|
-
def initialize (ctl_file)
|
141
|
+
def initialize (ctl_file, radius: nil)
|
132
142
|
@ctl_file = ctl_file
|
133
143
|
@entries = scan_ctl_file(ctl_file)
|
144
|
+
@radius = radius
|
134
145
|
parse_entries(@entries)
|
135
146
|
end
|
136
147
|
|
@@ -319,7 +330,13 @@ class GrADS::Gridded
|
|
319
330
|
end
|
320
331
|
|
321
332
|
def parse_pdef_lcc (args)
|
322
|
-
|
333
|
+
if defined? PROJ4 and defined? PROJ4::Proj
|
334
|
+
projlib = "proj4r"
|
335
|
+
elsif defined? PROJ
|
336
|
+
projlib = "simple-proj"
|
337
|
+
else
|
338
|
+
raise "can't find proj related library"
|
339
|
+
end
|
323
340
|
rlat = args[1].to_f
|
324
341
|
rlon = args[2].to_f
|
325
342
|
xi = args[3].to_f
|
@@ -330,21 +347,61 @@ class GrADS::Gridded
|
|
330
347
|
dx = args[8].to_f
|
331
348
|
dy = args[9].to_f
|
332
349
|
slat0 = slat1 > 0 ? 90 : -90
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
350
|
+
case projlib
|
351
|
+
when "proj4r"
|
352
|
+
if @radius
|
353
|
+
proj = PROJ4::Proj.new %{
|
354
|
+
+ellps=sphere +a=#{@radius} +b=#{@radius} +proj=lcc \
|
355
|
+
+lat_1=#{slat1} +lat_2=#{slat2} +lon_0=#{slon}
|
356
|
+
}
|
357
|
+
else
|
358
|
+
proj = PROJ4::Proj.new %{
|
359
|
+
+ellps=sphere +proj=lcc \
|
360
|
+
+lat_1=#{slat1} +lat_2=#{slat2} +lon_0=#{slon}
|
361
|
+
}
|
362
|
+
end
|
363
|
+
when "simple-proj"
|
364
|
+
if @radius
|
365
|
+
proj = PROJ.new %{
|
366
|
+
+ellps=sphere +a=#{@radius} +b=#{@radius} +proj=lcc \
|
367
|
+
+lat_1=#{slat1} +lat_2=#{slat2} +lon_0=#{slon}
|
368
|
+
}
|
369
|
+
else
|
370
|
+
proj = PROJ.new %{
|
371
|
+
+ellps=sphere +proj=lcc \
|
372
|
+
+lat_1=#{slat1} +lat_2=#{slat2} +lon_0=#{slon}
|
373
|
+
}
|
374
|
+
end
|
375
|
+
end
|
337
376
|
rx, ry = proj.forward(rlon, rlat)
|
338
377
|
rx0 = rx - (xi-1)*dx
|
339
378
|
ry0 = ry - (yi-1)*dy
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
379
|
+
case projlib
|
380
|
+
when "proj4r"
|
381
|
+
@forward = lambda { |lon, lat|
|
382
|
+
mx, my = proj.forward(lon, lat)
|
383
|
+
[(mx - rx0)/dx, (my - ry0)/dy]
|
384
|
+
}
|
385
|
+
@inverse = lambda { |fi, fj|
|
386
|
+
mx = fi*dx + rx0
|
387
|
+
my = fj*dy + ry0
|
388
|
+
proj.inverse(mx, my)
|
389
|
+
}
|
390
|
+
when "simple-proj"
|
391
|
+
@forward = lambda { |lon, lat|
|
392
|
+
mx, my = proj.forward_carray(lon, lat)
|
393
|
+
[(mx - rx0)/dx, (my - ry0)/dy]
|
394
|
+
}
|
395
|
+
@inverse = lambda { |fi, fj|
|
396
|
+
mx = fi*dx + rx0
|
397
|
+
my = fj*dy + ry0
|
398
|
+
proj.inverse_carray(mx, my)
|
399
|
+
}
|
400
|
+
end
|
401
|
+
@xy = lambda {
|
402
|
+
x = CArray.float(xsize).seq(rx0, dx)
|
403
|
+
y = CArray.float(ysize).seq(ry0, dy)
|
404
|
+
[x, y]
|
348
405
|
}
|
349
406
|
end
|
350
407
|
|
@@ -495,6 +552,18 @@ class GrADS::Gridded
|
|
495
552
|
def forward (rlon, rlat)
|
496
553
|
return @forward[rlon, rlat]
|
497
554
|
end
|
555
|
+
|
556
|
+
def lonlat
|
557
|
+
fi = CArray.float(xsize).seq
|
558
|
+
fj = CArray.float(ysize).seq
|
559
|
+
ii = fi[ysize,:%]
|
560
|
+
jj = fj[:%,xsize]
|
561
|
+
return @inverse[ii, jj]
|
562
|
+
end
|
563
|
+
|
564
|
+
def xy
|
565
|
+
return @xy[]
|
566
|
+
end
|
498
567
|
|
499
568
|
def var (name)
|
500
569
|
unless @varnames.include?(name)
|