ctioga2 0.13.1 → 0.14
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/Changelog +26 -0
- data/bin/ct2-make-movie +4 -1
- data/bin/ctioga2 +1 -1
- data/lib/ctioga2/commands/commands.rb +2 -0
- data/lib/ctioga2/commands/doc/doc.rb +1 -1
- data/lib/ctioga2/commands/doc/documentation-commands.rb +38 -0
- data/lib/ctioga2/commands/doc/html.rb +84 -0
- data/lib/ctioga2/commands/general-commands.rb +20 -1
- data/lib/ctioga2/commands/general-functions.rb +26 -0
- data/lib/ctioga2/commands/general-types.rb +1 -0
- data/lib/ctioga2/commands/instruction.rb +61 -0
- data/lib/ctioga2/commands/interpreter.rb +12 -2
- data/lib/ctioga2/data/datacolumn.rb +38 -0
- data/lib/ctioga2/data/dataset.rb +6 -5
- data/lib/ctioga2/data/filters.rb +12 -5
- data/lib/ctioga2/data/stack.rb +105 -22
- data/lib/ctioga2/graphics/elements.rb +1 -1
- data/lib/ctioga2/graphics/elements/curve2d.rb +1 -1
- data/lib/ctioga2/graphics/elements/element.rb +29 -10
- data/lib/ctioga2/graphics/elements/primitive.rb +26 -2
- data/lib/ctioga2/graphics/elements/subplot.rb +7 -1
- data/lib/ctioga2/graphics/generator.rb +1 -2
- data/lib/ctioga2/graphics/legends/area.rb +3 -0
- data/lib/ctioga2/graphics/root.rb +18 -2
- data/lib/ctioga2/graphics/styles/curve.rb +6 -0
- data/lib/ctioga2/graphics/styles/drawable.rb +4 -0
- data/lib/ctioga2/graphics/styles/factory.rb +4 -5
- data/lib/ctioga2/graphics/styles/plot-types.rb +22 -7
- data/lib/ctioga2/graphics/subplot-commands.rb +2 -4
- data/lib/ctioga2/graphics/types.rb +17 -0
- data/lib/ctioga2/graphics/types/boundaries.rb +10 -0
- data/lib/ctioga2/graphics/types/boxes.rb +18 -0
- data/lib/ctioga2/graphics/types/dimensions.rb +4 -0
- data/lib/ctioga2/graphics/types/grid.rb +98 -4
- data/lib/ctioga2/graphics/types/point.rb +9 -0
- data/lib/ctioga2/metabuilder/types/lists.rb +1 -1
- data/lib/ctioga2/metabuilder/types/styles.rb +5 -3
- data/lib/ctioga2/plotmaker.rb +28 -5
- data/lib/ctioga2/postprocess.rb +28 -0
- data/lib/ctioga2/ruby.rb +7 -0
- data/lib/ctioga2/utils.rb +45 -0
- data/lib/ctioga2/version.rb +2 -2
- metadata +4 -3
@@ -133,7 +133,13 @@ module CTioga2
|
|
133
133
|
end
|
134
134
|
for k, b in bounds
|
135
135
|
if ! b.valid?
|
136
|
-
|
136
|
+
if b.nan?
|
137
|
+
error { "Invalid computed range, you have NaNs in your data (missing data ?)" }
|
138
|
+
elsif b.infinite?
|
139
|
+
error { "Infinite computed range, you have infinite numbers in your data" }
|
140
|
+
else
|
141
|
+
error { "Invalid computed range, you probably have only empty datasets" }
|
142
|
+
end
|
137
143
|
bounds[k] = Types::SimpleRange.new(0.0,1.0)
|
138
144
|
end
|
139
145
|
end
|
@@ -88,8 +88,7 @@ module CTioga2
|
|
88
88
|
old_opts = options.dup
|
89
89
|
# Now, we trim options unrelated to the plotting
|
90
90
|
options.delete_if { |k,v|
|
91
|
-
! Graphics::Styles::
|
92
|
-
CurveStyleFactory::PlotCommandOptions.key?(k)
|
91
|
+
! Graphics::Styles::CurveStyleFactory::PlotCommandOptions.key?(k)
|
93
92
|
}
|
94
93
|
|
95
94
|
begin
|
@@ -137,11 +137,27 @@ module CTioga2
|
|
137
137
|
#
|
138
138
|
# For the sake of convenience, returns the newly created
|
139
139
|
# Elements::Subplot
|
140
|
-
def subplot(opts)
|
140
|
+
def subplot(opts, box = nil)
|
141
141
|
if ! @current_container
|
142
142
|
enter_subobject(Elements::Container.new(nil, self, {}))
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
|
+
o = opts.dup
|
146
|
+
o["class"] ||= []
|
147
|
+
|
148
|
+
# We add automatic classes from the box
|
149
|
+
#
|
150
|
+
# Most of the time empty, for sure.
|
151
|
+
if box
|
152
|
+
o["class"] += box.classes
|
153
|
+
end
|
154
|
+
|
155
|
+
subplot = Elements::Subplot.new(@current_container, self, o)
|
156
|
+
|
157
|
+
if box
|
158
|
+
subplot.subframe = box
|
159
|
+
end
|
160
|
+
|
145
161
|
enter_subobject(subplot)
|
146
162
|
return subplot
|
147
163
|
end
|
@@ -91,6 +91,12 @@ module CTioga2
|
|
91
91
|
# A colormap for markers (only for XYZ data)
|
92
92
|
typed_attribute :marker_color_map, 'colormap'
|
93
93
|
|
94
|
+
# A colormap for the line of markers (only for XYZ data)
|
95
|
+
typed_attribute :marker_line_color_map, 'colormap'
|
96
|
+
|
97
|
+
# A colormap for the fill color of markers (only for XYZ data)
|
98
|
+
typed_attribute :marker_fill_color_map, 'colormap'
|
99
|
+
|
94
100
|
# If this is specified when choosing the marker scale as a
|
95
101
|
# function of a given Z value, then the original Z segment is
|
96
102
|
# mapped to min_scale -> scale.
|
@@ -50,10 +50,14 @@ module CTioga2
|
|
50
50
|
class StrokeStyle < LineStyle
|
51
51
|
# The color
|
52
52
|
typed_attribute :color, 'color-or-false'
|
53
|
+
|
54
|
+
# The line cap
|
55
|
+
typed_attribute :cap, 'line-cap'
|
53
56
|
|
54
57
|
# Sets the stroke style to a FigureMaker object, _t_.
|
55
58
|
def set_stroke_style(t)
|
56
59
|
t.stroke_color = @color if @color
|
60
|
+
t.line_cap = @cap if @cap
|
57
61
|
super
|
58
62
|
end
|
59
63
|
|
@@ -353,6 +353,8 @@ module CTioga2
|
|
353
353
|
|
354
354
|
simple_parameter 'line_style', 'line style', Sets::LineStyleSets
|
355
355
|
|
356
|
+
simple_parameter 'line_cap', 'line cap', nil
|
357
|
+
|
356
358
|
# Markers
|
357
359
|
simple_parameter 'marker', 'marker', Sets::MarkerSets, '-m'
|
358
360
|
|
@@ -409,12 +411,9 @@ module CTioga2
|
|
409
411
|
|
410
412
|
simple_parameter 'zaxis', "name for the Z axis"
|
411
413
|
|
412
|
-
## @todo For xy-parametric, there should be a way to specify
|
413
|
-
## to which z value the maps apply (ie lines = y2, marker =
|
414
|
-
## y3...). Although for readability, it is probably better
|
415
|
-
## to avoid that...
|
416
414
|
simple_parameter 'marker_color_map', 'color map for markers'
|
417
|
-
|
415
|
+
simple_parameter 'marker_line_color_map', 'color map for the lines of markers'
|
416
|
+
simple_parameter 'marker_fill_color_map', 'color map for the lines of markers'
|
418
417
|
simple_parameter 'split_on_nan', 'split on NaN'
|
419
418
|
|
420
419
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
# contour.rb: the style of a contour plot
|
2
3
|
# copyright (c) 2009 by Vincent Fourmond
|
3
4
|
|
@@ -24,6 +25,8 @@ module CTioga2
|
|
24
25
|
|
25
26
|
StyleAspectRE = {
|
26
27
|
/^marker[_-]color$/i => :marker_color,
|
28
|
+
/^marker[_-]fill[_-]color$/i => :marker_fill_color,
|
29
|
+
/^marker[_-]line[_-]color$/i => :marker_line_color,
|
27
30
|
/^marker[_-](size|scale)$/i => :marker_scale,
|
28
31
|
}
|
29
32
|
|
@@ -48,6 +51,12 @@ EOD
|
|
48
51
|
# What is the z2 axis
|
49
52
|
typed_attribute :z2, 'style-aspect'
|
50
53
|
|
54
|
+
# What is the z3 axis
|
55
|
+
typed_attribute :z3, 'style-aspect'
|
56
|
+
|
57
|
+
# What is the z4 axis
|
58
|
+
typed_attribute :z4, 'style-aspect'
|
59
|
+
|
51
60
|
def initialize
|
52
61
|
@z1 = :marker_color
|
53
62
|
end
|
@@ -55,7 +64,7 @@ EOD
|
|
55
64
|
def prepare
|
56
65
|
@reversed = {}
|
57
66
|
|
58
|
-
|
67
|
+
4.times do |i|
|
59
68
|
val = self.send("z#{i+1}")
|
60
69
|
if val
|
61
70
|
@reversed[val] = i
|
@@ -106,12 +115,18 @@ EOD
|
|
106
115
|
|
107
116
|
end
|
108
117
|
|
109
|
-
|
110
|
-
|
111
|
-
if
|
112
|
-
|
113
|
-
|
114
|
-
|
118
|
+
for bs in [:color, :line_color, :fill_color]
|
119
|
+
stl = "marker_#{bs}".to_sym
|
120
|
+
if @reversed[stl]
|
121
|
+
idx = @reversed[stl]
|
122
|
+
if idx < zvalue.size
|
123
|
+
map = curve_style.send("#{stl}_map")
|
124
|
+
if map
|
125
|
+
style.send("#{bs}=",map.z_color(zvalue[idx],
|
126
|
+
zmin[idx],
|
127
|
+
zmax[idx]))
|
128
|
+
end
|
129
|
+
end
|
115
130
|
end
|
116
131
|
end
|
117
132
|
|
@@ -135,8 +135,7 @@ EOD
|
|
135
135
|
CmdArg.new('box'),
|
136
136
|
], Elements::TiogaElement::StyleBaseOptions) do |plotmaker, box, opts|
|
137
137
|
Log::debug { "Starting a subplot with specs #{box.inspect}" }
|
138
|
-
subplot = plotmaker.root_object.subplot(opts)
|
139
|
-
subplot.subframe = box
|
138
|
+
subplot = plotmaker.root_object.subplot(opts, box)
|
140
139
|
end
|
141
140
|
|
142
141
|
InsetCommand.describe('Begins a new inset',
|
@@ -153,8 +152,7 @@ EOD
|
|
153
152
|
CmdArg.new('box'),
|
154
153
|
], Elements::TiogaElement::StyleBaseOptions) do |plotmaker, box,opts|
|
155
154
|
plotmaker.root_object.leave_subobject
|
156
|
-
subplot = plotmaker.root_object.subplot(opts)
|
157
|
-
subplot.subframe = box
|
155
|
+
subplot = plotmaker.root_object.subplot(opts, box)
|
158
156
|
end
|
159
157
|
|
160
158
|
NextInsetCommand.describe('Ends the previous inset and begins a new one',
|
@@ -102,6 +102,23 @@ a series of comma-separated numbers which are the length of the
|
|
102
102
|
strokes and gaps, or @no@, @none@ or @off@ to mean no line.
|
103
103
|
EOD
|
104
104
|
|
105
|
+
LineCapType =
|
106
|
+
CmdType.new('line-cap', {
|
107
|
+
:type => :list,
|
108
|
+
:list => {},
|
109
|
+
:shortcuts => {
|
110
|
+
'butt' => Tioga::FigureConstants::LINE_CAP_BUTT,
|
111
|
+
'round' => Tioga::FigureConstants::LINE_CAP_ROUND,
|
112
|
+
'square' => Tioga::FigureConstants::LINE_CAP_SQUARE,
|
113
|
+
}
|
114
|
+
}, <<EOD)
|
115
|
+
A line cap style, i.e. how the line extends beyond its last point.
|
116
|
+
Available choices:
|
117
|
+
* @round@ (extends as a half circle default)
|
118
|
+
* @butt@ (does not extend at all)
|
119
|
+
* @square@ (extends as a half square)
|
120
|
+
EOD
|
121
|
+
|
105
122
|
MarkerType =
|
106
123
|
CmdType.new('marker', {
|
107
124
|
:type => :tioga_marker,
|
@@ -51,6 +51,16 @@ module CTioga2
|
|
51
51
|
Utils::finite_number?(@last))
|
52
52
|
end
|
53
53
|
|
54
|
+
def nan?
|
55
|
+
return (Utils::nan_number?(@first) or
|
56
|
+
Utils::nan_number?(@last))
|
57
|
+
end
|
58
|
+
|
59
|
+
def infinite?
|
60
|
+
return (Utils::infinite_number?(@first) or
|
61
|
+
Utils::infinite_number?(@last))
|
62
|
+
end
|
63
|
+
|
54
64
|
# Minimum value
|
55
65
|
def min
|
56
66
|
@first < @last ? @first : @last
|
@@ -44,6 +44,24 @@ module CTioga2
|
|
44
44
|
xl, yt, xr, yb = self.to_frame_coordinates(t)
|
45
45
|
return [xl, 1 - xr, 1 - yt, yb]
|
46
46
|
end
|
47
|
+
|
48
|
+
# Runs the block within the context of the box.
|
49
|
+
def within_frames(t, frame_coords = true)
|
50
|
+
t.context do
|
51
|
+
t.subfigure(self.to_frame_margins(t)) do
|
52
|
+
if frame_coords
|
53
|
+
t.set_bounds([0, 1, 1, 0])
|
54
|
+
end
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# The classes enumerated here get added to the class list of
|
61
|
+
# the subwindow
|
62
|
+
def classes
|
63
|
+
return []
|
64
|
+
end
|
47
65
|
|
48
66
|
end
|
49
67
|
|
@@ -77,6 +77,10 @@ module CTioga2
|
|
77
77
|
return Dimension.new(@type, -@value, @orientation)
|
78
78
|
end
|
79
79
|
|
80
|
+
def *(fct)
|
81
|
+
return Dimension.new(@type, @value*fct, @orientation)
|
82
|
+
end
|
83
|
+
|
80
84
|
# Returns a dimension corresponding to the distance.
|
81
85
|
def self.get_distance(t, dx, dy)
|
82
86
|
dx = make_dimension(dx, :x).to_bp(t)
|
@@ -31,7 +31,7 @@ module CTioga2
|
|
31
31
|
|
32
32
|
OptionHashRE = /([\w-]+)\s*=\s*([^,]+),?\s*/
|
33
33
|
|
34
|
-
GridBoxRE = /^\s*grid:(\d+(?:-\d+)?)\s*,\s*(\d+(?:-\d+)?)(?:,(#{OptionHashRE}+))?\s*$/
|
34
|
+
GridBoxRE = /^\s*grid:(?:(\d+(?:-\d+)?)\s*,\s*(\d+(?:-\d+)?)|(next))(?:,(#{OptionHashRE}+))?\s*$/
|
35
35
|
|
36
36
|
# This hash helps to convert from a hash-based representation
|
37
37
|
# of frame coordinates to the array-based one.
|
@@ -44,11 +44,31 @@ module CTioga2
|
|
44
44
|
'yb' => 3
|
45
45
|
}
|
46
46
|
|
47
|
+
# The position of the element in the grid (arrays [left,right]
|
48
|
+
# or [top, bottom])
|
49
|
+
attr_accessor :x,:y
|
50
|
+
|
47
51
|
def self.from_text(txt)
|
48
52
|
if txt =~ GridBoxRE
|
49
|
-
|
50
|
-
|
51
|
-
|
53
|
+
if $3 # next
|
54
|
+
x = 0
|
55
|
+
y = 0
|
56
|
+
grd = GridLayout.current_grid
|
57
|
+
lastel = grd.elements.last
|
58
|
+
if lastel
|
59
|
+
x = lastel.x.max + 1
|
60
|
+
y = lastel.y.max
|
61
|
+
if x >= grd.xsize
|
62
|
+
x = 0
|
63
|
+
y += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
return GridBox.new(grd, x, y, $4)
|
67
|
+
else
|
68
|
+
return GridBox.new(GridLayout.current_grid, $1, $2,
|
69
|
+
$4) # The latter being to remove
|
70
|
+
# the initial comma
|
71
|
+
end
|
52
72
|
else
|
53
73
|
raise "#{txt} is not a grid box."
|
54
74
|
end
|
@@ -63,6 +83,19 @@ module CTioga2
|
|
63
83
|
return [str.to_i, str.to_i]
|
64
84
|
end
|
65
85
|
end
|
86
|
+
|
87
|
+
# Returns false if the position given by @x and @y are within
|
88
|
+
# the grid
|
89
|
+
def within_grid?
|
90
|
+
if @x.min < 0 || @x.max >= @grid.xsize
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
if @y.min < 0 || @y.max >= @grid.ysize
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
|
66
99
|
|
67
100
|
def initialize(grid, x, y, options = {})
|
68
101
|
if options.is_a? String
|
@@ -83,6 +116,12 @@ module CTioga2
|
|
83
116
|
@x = parse_range(x).sort
|
84
117
|
@y = parse_range(y).sort
|
85
118
|
@overrides = options || {}
|
119
|
+
|
120
|
+
if ! within_grid?
|
121
|
+
raise "Grid element #{x},#{y} is outside grid boundaries (#{@grid.xsize}x#{@grid.ysize})"
|
122
|
+
end
|
123
|
+
|
124
|
+
@grid.elements << self
|
86
125
|
end
|
87
126
|
|
88
127
|
def to_frame_coordinates(t)
|
@@ -99,6 +138,48 @@ module CTioga2
|
|
99
138
|
end
|
100
139
|
return a
|
101
140
|
end
|
141
|
+
|
142
|
+
def classes
|
143
|
+
rv = []
|
144
|
+
hsh = {
|
145
|
+
'left' => @x.min == 0,
|
146
|
+
'right' => @x.max + 1 == @grid.xsize,
|
147
|
+
'top' => @y.min == 0,
|
148
|
+
'bottom' => @y.max + 1 == @grid.ysize
|
149
|
+
}
|
150
|
+
for k, v in hsh
|
151
|
+
if v
|
152
|
+
rv << "grid-#{k}"
|
153
|
+
else
|
154
|
+
rv << "grid-non-#{k}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
xv = nil
|
159
|
+
yv = nil
|
160
|
+
if @x.min == @x.max
|
161
|
+
xv = @x.min
|
162
|
+
rv << "grid-column-#{xv}"
|
163
|
+
if xv.even?
|
164
|
+
rv << "grid-even-column"
|
165
|
+
else
|
166
|
+
rv << "grid-odd-column"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
if @y.min == @y.max
|
170
|
+
yv = @y.min
|
171
|
+
rv << "grid-row-#{yv}"
|
172
|
+
if yv.even?
|
173
|
+
rv << "grid-even-row"
|
174
|
+
else
|
175
|
+
rv << "grid-odd-row"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
if xv && yv
|
179
|
+
rv << "grid-#{xv}-#{yv}"
|
180
|
+
end
|
181
|
+
return rv
|
182
|
+
end
|
102
183
|
end
|
103
184
|
|
104
185
|
# This class provides a grid-like layout through the use of a grid
|
@@ -125,6 +206,9 @@ module CTioga2
|
|
125
206
|
# Vertical scales
|
126
207
|
attr_accessor :vscales
|
127
208
|
|
209
|
+
# The GridBox objects we've seen so far
|
210
|
+
attr_accessor :elements
|
211
|
+
|
128
212
|
def initialize(nup = "2x2")
|
129
213
|
if nup.respond_to?(:split)
|
130
214
|
if nup =~ /,/
|
@@ -156,6 +240,8 @@ module CTioga2
|
|
156
240
|
|
157
241
|
@hscales ||= [1] * @nup[0]
|
158
242
|
@vscales ||= [1] * @nup[1]
|
243
|
+
|
244
|
+
@elements = []
|
159
245
|
end
|
160
246
|
|
161
247
|
# The grid currently in use.
|
@@ -169,6 +255,14 @@ module CTioga2
|
|
169
255
|
return @current_grid
|
170
256
|
end
|
171
257
|
|
258
|
+
def xsize
|
259
|
+
return @hscales.size
|
260
|
+
end
|
261
|
+
|
262
|
+
def ysize
|
263
|
+
return @vscales.size
|
264
|
+
end
|
265
|
+
|
172
266
|
# Compute the frame coordinates fo the x,y element of the
|
173
267
|
# grid. They are numbered from the top,left element.
|
174
268
|
def frame_coordinates(t, x, y)
|
@@ -216,6 +216,15 @@ module CTioga2
|
|
216
216
|
@valign = valign
|
217
217
|
end
|
218
218
|
|
219
|
+
def self.from_point(pt, halign = :center, valign = :center)
|
220
|
+
a = AlignedPoint.new
|
221
|
+
a.x = pt.x
|
222
|
+
a.y = pt.y
|
223
|
+
a.halign = halign
|
224
|
+
a.valign = valign
|
225
|
+
return a
|
226
|
+
end
|
227
|
+
|
219
228
|
# Returns frame coordinates corresponding to the point, the
|
220
229
|
# alignment and the given size in figure coordinates
|
221
230
|
def to_frame_coordinates(t, width, height)
|