ctioga2 0.11 → 0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog +17 -0
- data/lib/ctioga2/commands/commands.rb +2 -1
- data/lib/ctioga2/commands/doc/documentation-commands.rb +2 -1
- data/lib/ctioga2/commands/doc/html.rb +27 -0
- data/lib/ctioga2/commands/general-commands.rb +13 -0
- data/lib/ctioga2/commands/type.rb +1 -1
- data/lib/ctioga2/data/dataset.rb +210 -0
- data/lib/ctioga2/data/stack.rb +1 -1
- data/lib/ctioga2/graphics/elements/primitive.rb +8 -6
- data/lib/ctioga2/graphics/elements/subplot.rb +0 -7
- data/lib/ctioga2/graphics/elements/tangent.rb +3 -1
- data/lib/ctioga2/graphics/elements/xyz-map.rb +47 -28
- data/lib/ctioga2/graphics/styles.rb +1 -0
- data/lib/ctioga2/graphics/styles/arrows.rb +141 -1
- data/lib/ctioga2/graphics/styles/axes.rb +18 -1
- data/lib/ctioga2/graphics/styles/base.rb +41 -2
- data/lib/ctioga2/graphics/styles/box.rb +1 -1
- data/lib/ctioga2/graphics/styles/drawable.rb +60 -54
- data/lib/ctioga2/graphics/styles/errorbar.rb +10 -3
- data/lib/ctioga2/graphics/styles/factory.rb +80 -9
- data/lib/ctioga2/graphics/styles/plot.rb +1 -1
- data/lib/ctioga2/graphics/styles/scope.rb +72 -0
- data/lib/ctioga2/graphics/styles/sets.rb +2 -1
- data/lib/ctioga2/graphics/types.rb +1 -1
- data/lib/ctioga2/graphics/types/dimensions.rb +48 -0
- data/lib/ctioga2/log.rb +12 -0
- data/lib/ctioga2/metabuilder/type.rb +32 -20
- data/lib/ctioga2/metabuilder/types/strings.rb +2 -2
- data/lib/ctioga2/plotmaker.rb +14 -0
- data/lib/ctioga2/utils.rb +51 -3
- data/lib/ctioga2/version.rb +2 -2
- metadata +5 -3
@@ -40,6 +40,9 @@ module CTioga2
|
|
40
40
|
# parameter. It is a hash.
|
41
41
|
attr_accessor :sets
|
42
42
|
|
43
|
+
# The name of the default set, when it isn't 'default'
|
44
|
+
attr_accessor :default_set
|
45
|
+
|
43
46
|
# The description of the parameter.
|
44
47
|
attr_accessor :description
|
45
48
|
|
@@ -60,8 +63,16 @@ module CTioga2
|
|
60
63
|
def initialize(name, type, sets, description,
|
61
64
|
short_option = nil, disable_cmds = false)
|
62
65
|
@name = name
|
63
|
-
@type = type
|
64
|
-
|
66
|
+
@type = type
|
67
|
+
if sets
|
68
|
+
# If the sets is an array, it is of the form [sets, 'default set']
|
69
|
+
if sets.is_a? Array
|
70
|
+
@sets = sets[0]
|
71
|
+
@default_set = sets[1]
|
72
|
+
else
|
73
|
+
@sets = sets
|
74
|
+
end
|
75
|
+
end
|
65
76
|
@description = description
|
66
77
|
@short_option = short_option
|
67
78
|
@disable_commands = disable_cmds
|
@@ -81,7 +92,9 @@ module CTioga2
|
|
81
92
|
# Returns a suitable default set for the given object.
|
82
93
|
def default_set
|
83
94
|
return nil unless @sets
|
84
|
-
if @
|
95
|
+
if @default_set
|
96
|
+
return @sets[@default_set]
|
97
|
+
elsif @sets.key? 'default'
|
85
98
|
return @sets['default']
|
86
99
|
else
|
87
100
|
@sets.each do |k,v|
|
@@ -249,22 +262,36 @@ module CTioga2
|
|
249
262
|
}
|
250
263
|
@parameters_carrays = {}
|
251
264
|
for target, param in self.class.parameters
|
265
|
+
# There should be a way to do that !
|
252
266
|
set = param.default_set
|
253
267
|
if set
|
254
268
|
@parameters_carrays[target] = CircularArray.new(set)
|
255
269
|
end
|
256
270
|
end
|
271
|
+
|
272
|
+
@next_style = nil
|
273
|
+
end
|
274
|
+
|
275
|
+
# Sets the style to be returned from the next call to #next
|
276
|
+
# (not counting the effect of the options passed)
|
277
|
+
def set_next_style(stl)
|
278
|
+
@next_style = stl
|
257
279
|
end
|
258
280
|
|
259
281
|
# Gets the style for the next curve. The _one_time_ hash
|
260
282
|
# contains values 'parameter name' (name, and not target) =>
|
261
283
|
# value that are used for this time only.
|
262
284
|
def next(one_time = {})
|
263
|
-
|
264
|
-
|
265
|
-
|
285
|
+
if @next_style
|
286
|
+
base = @next_style
|
287
|
+
@next_style = nil
|
288
|
+
else
|
289
|
+
base = {}
|
290
|
+
for target, array in @parameters_carrays
|
291
|
+
base[target] = array.next
|
292
|
+
end
|
293
|
+
base.merge!(@override_parameters)
|
266
294
|
end
|
267
|
-
base.merge!(@override_parameters)
|
268
295
|
base.merge!(hash_name_to_target(one_time))
|
269
296
|
return CurveStyle.from_hash(resolve_links(base))
|
270
297
|
end
|
@@ -327,18 +354,29 @@ module CTioga2
|
|
327
354
|
simple_parameter 'line_style', 'line style', Sets::LineStyleSets
|
328
355
|
|
329
356
|
# Markers
|
330
|
-
simple_parameter
|
357
|
+
simple_parameter 'marker', 'marker', Sets::MarkerSets, '-m'
|
331
358
|
|
332
359
|
simple_parameter 'marker_color', "marker color", Sets::ColorSets
|
333
360
|
|
361
|
+
simple_parameter 'marker_fill_color', "marker fill color", [Sets::ColorSets, 'nil']
|
362
|
+
|
363
|
+
simple_parameter 'marker_line_color', "marker stroke color", [Sets::ColorSets, 'nil']
|
364
|
+
|
334
365
|
simple_parameter 'marker_scale', "marker scale", Sets::LineWidthSets
|
335
366
|
|
367
|
+
simple_parameter 'marker_angle', "marker angle", nil
|
368
|
+
|
369
|
+
simple_parameter 'marker_line_width', "marker line width", nil
|
370
|
+
|
336
371
|
simple_parameter 'marker_min_scale', "marker scale", nil
|
337
372
|
|
338
373
|
# Error bars:
|
339
374
|
simple_parameter 'error_bar_color', "error bar color",
|
340
375
|
Sets::ColorSets
|
341
376
|
|
377
|
+
simple_parameter 'error_bar_line_width', "error bar line width",
|
378
|
+
Sets::LineWidthSets
|
379
|
+
|
342
380
|
# Location:
|
343
381
|
define_parameter 'location_xaxis', 'xaxis',
|
344
382
|
nil, "X axis", nil, true
|
@@ -470,7 +508,40 @@ module CTioga2
|
|
470
508
|
return tv
|
471
509
|
end
|
472
510
|
end
|
473
|
-
|
511
|
+
|
512
|
+
SkipCommand =
|
513
|
+
Cmd.new("skip",nil,"--skip",
|
514
|
+
[], {'number' => CmdArg.new("integer")}
|
515
|
+
) do |plotmaker, opts|
|
516
|
+
number = opts['number'] || 1
|
517
|
+
fct = plotmaker.curve_generator.style_factory
|
518
|
+
while number > 0
|
519
|
+
number -= 1
|
520
|
+
fct.next
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
SkipCommand.describe('Skips next curve style',
|
525
|
+
<<EOH, CurveStyleFactory::CurveStyleGroup)
|
526
|
+
This command acts as if one (or @number@) dataset had been drawn with
|
527
|
+
respect to the style of the next dataset to be drawn.
|
528
|
+
EOH
|
529
|
+
|
530
|
+
ReuseCommand =
|
531
|
+
Cmd.new("reuse-style",nil,"--reuse-style",
|
532
|
+
[CmdArg.new('object')], {}
|
533
|
+
) do |plotmaker, obj, opts|
|
534
|
+
stl = obj.curve_style.to_hash
|
535
|
+
plotmaker.curve_generator.style_factory.set_next_style(stl)
|
536
|
+
end
|
537
|
+
|
538
|
+
ReuseCommand.describe('Reuse the style of a previous curve',
|
539
|
+
<<EOH, CurveStyleFactory::CurveStyleGroup)
|
540
|
+
After using this command, the next curve will have the same style as the
|
541
|
+
curve whose name was given as the first argument (it is the name given to
|
542
|
+
the `/id=` option to plot.
|
543
|
+
EOH
|
544
|
+
end
|
474
545
|
|
475
546
|
# Now, we document some aspects of the above created commands
|
476
547
|
c = Commands::Command
|
@@ -439,7 +439,7 @@ EOH
|
|
439
439
|
style = AxisStyle.current_axis_style(plotmaker, w)
|
440
440
|
style.set_from_hash(opts)
|
441
441
|
rescue Exception => e
|
442
|
-
error {"Error while setting style of axis: #{w} -- #{e}"}
|
442
|
+
Log::error {"Error while setting style of axis: #{w} -- #{e}"}
|
443
443
|
end
|
444
444
|
end
|
445
445
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# scope.rb: containers that provide translation and scaling capacities
|
2
|
+
# copyright (c) 2015 by Vincent Fourmond
|
3
|
+
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
13
|
+
|
14
|
+
require 'ctioga2/utils'
|
15
|
+
require 'ctioga2/log'
|
16
|
+
|
17
|
+
# This module contains all the classes used by ctioga
|
18
|
+
module CTioga2
|
19
|
+
|
20
|
+
module Graphics
|
21
|
+
|
22
|
+
# All the styles
|
23
|
+
module Styles
|
24
|
+
|
25
|
+
# This style represents a scope, ie something that translates
|
26
|
+
# (first) and scales (second) figure coordinates.
|
27
|
+
class ScopeStyle < BasicStyle
|
28
|
+
|
29
|
+
typed_attribute 'xshift', 'dimension'
|
30
|
+
typed_attribute 'xscale', 'float'
|
31
|
+
|
32
|
+
typed_attribute 'yshift', 'dimension'
|
33
|
+
typed_attribute 'yscale', 'float'
|
34
|
+
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
end
|
38
|
+
|
39
|
+
# applies the transformation to the current figure coordinates
|
40
|
+
def apply_to_figure(t)
|
41
|
+
bl = t.bounds_left
|
42
|
+
br = t.bounds_right
|
43
|
+
bt = t.bounds_top
|
44
|
+
bb = t.bounds_bottom
|
45
|
+
|
46
|
+
if @xshift
|
47
|
+
dx = @xshift.to_figure(t,:x)
|
48
|
+
bl -= dx
|
49
|
+
br -= dx
|
50
|
+
end
|
51
|
+
|
52
|
+
if @yshift
|
53
|
+
dy = @yshift.to_figure(t,:y)
|
54
|
+
bt -= dy
|
55
|
+
bb -= dy
|
56
|
+
end
|
57
|
+
|
58
|
+
if @xscale
|
59
|
+
bl, br = *Utils::scale_segment(bl, br, 1/@xscale)
|
60
|
+
end
|
61
|
+
if @yscale
|
62
|
+
bt, bb = *Utils::scale_segment(bt, bb, 1/@yscale)
|
63
|
+
end
|
64
|
+
|
65
|
+
t.set_bounds([bl, br, bt, bb])
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -51,10 +51,58 @@ module CTioga2
|
|
51
51
|
# _value_ oriented along the given _orientation_
|
52
52
|
def initialize(type, value, orientation = :x)
|
53
53
|
@type = type
|
54
|
+
if not @type.is_a? Symbol
|
55
|
+
raise "Invalid value for the dimension type: '#{@type}'"
|
56
|
+
end
|
54
57
|
@value = value
|
55
58
|
@orientation = orientation
|
56
59
|
end
|
57
60
|
|
61
|
+
def self.make_dimension(val, orient = :x, default = :figure)
|
62
|
+
if val.is_a? Dimension
|
63
|
+
return val
|
64
|
+
else
|
65
|
+
return Dimension.new(default, val, orient)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Gets the angle along the given direction
|
70
|
+
def self.get_angle(t, dx, dy)
|
71
|
+
dx = make_dimension(dx, :x).to_bp(t)
|
72
|
+
dy = make_dimension(dy, :y).to_bp(t)
|
73
|
+
return 180 * Math::atan2(dy, dx)/Math::PI
|
74
|
+
end
|
75
|
+
|
76
|
+
def -@
|
77
|
+
return Dimension.new(@type, -@value, @orientation)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a dimension corresponding to the distance.
|
81
|
+
def self.get_distance(t, dx, dy)
|
82
|
+
dx = make_dimension(dx, :x).to_bp(t)
|
83
|
+
dy = make_dimension(dy, :y).to_bp(t)
|
84
|
+
return Dimension.new(:bp, (dx**2 + dy**2)**0.5)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Adjusts the given line by adding the dimensions on the left
|
88
|
+
# and on the right (can be negative).
|
89
|
+
#
|
90
|
+
# Returns the new [x1, y1, x2, y2]
|
91
|
+
def self.adjust_line(t, x1, y1, x2, y2, left, right)
|
92
|
+
dx = x2 - x1
|
93
|
+
dy = y2 - y1
|
94
|
+
dst = get_distance(t, x2-x1, y2-y1).to_bp(t)
|
95
|
+
lf = left.to_bp(t)/dst
|
96
|
+
rf = right.to_bp(t)/dst
|
97
|
+
|
98
|
+
x1 -= lf * dx
|
99
|
+
y1 -= lf * dy
|
100
|
+
x2 += rf * dx
|
101
|
+
y2 += rf * dy
|
102
|
+
return [x1, y1, x2, y2]
|
103
|
+
end
|
104
|
+
|
105
|
+
|
58
106
|
# Converts the Dimension to the *figure* coordinates of the
|
59
107
|
# *current* figure in _t_.
|
60
108
|
#
|
data/lib/ctioga2/log.rb
CHANGED
@@ -35,26 +35,31 @@ module CTioga2
|
|
35
35
|
# is not implemented yet.
|
36
36
|
def debug(channel = nil)
|
37
37
|
@@logger.debug {yield + Log.context}
|
38
|
+
@@counts[:debug] += 1
|
38
39
|
end
|
39
40
|
|
40
41
|
# Prints a warning message
|
41
42
|
def warn
|
42
43
|
@@logger.warn {yield + Log.context}
|
44
|
+
@@counts[:warn] += 1
|
43
45
|
end
|
44
46
|
|
45
47
|
# Prints an informational message
|
46
48
|
def info
|
47
49
|
@@logger.info {yield + Log.context}
|
50
|
+
@@counts[:info] += 1
|
48
51
|
end
|
49
52
|
|
50
53
|
# Prints an error message
|
51
54
|
def error
|
52
55
|
@@logger.error {yield + Log.context}
|
56
|
+
@@counts[:error] += 1
|
53
57
|
end
|
54
58
|
|
55
59
|
# Prints a fatal error message and initiates program termination.
|
56
60
|
def fatal
|
57
61
|
@@logger.fatal {yield + Log.context}
|
62
|
+
@@counts[:fatal] += 1 # Though not very useful
|
58
63
|
exit 1 # Fatal error.
|
59
64
|
end
|
60
65
|
|
@@ -70,8 +75,15 @@ module CTioga2
|
|
70
75
|
Logger::Formatter::Format.replace("[%4$s] %6$s\n")
|
71
76
|
@@logger = Logger.new(stream)
|
72
77
|
@@logger.level = Logger::WARN # Warnings and more only by default
|
78
|
+
@@counts = {}
|
79
|
+
for k in [:error, :debug, :warn, :info, :fatal]
|
80
|
+
@@counts[k] = 0
|
81
|
+
end
|
73
82
|
end
|
74
83
|
|
84
|
+
def self.counts
|
85
|
+
return @@counts
|
86
|
+
end
|
75
87
|
|
76
88
|
# Logs to the target file, and fall back onto stderr should
|
77
89
|
# opening fail.
|
@@ -87,6 +87,8 @@ module CTioga2
|
|
87
87
|
# to a Type child
|
88
88
|
@@types = { }
|
89
89
|
|
90
|
+
@@type_names = {}
|
91
|
+
|
90
92
|
# The initial type specification that was given to the Type
|
91
93
|
attr_accessor :type
|
92
94
|
|
@@ -144,6 +146,7 @@ module CTioga2
|
|
144
146
|
"from #{@@types[name]} to #{self}" }
|
145
147
|
end
|
146
148
|
@@types[name] = self
|
149
|
+
@@type_names[self] = name
|
147
150
|
self.send(:define_method,:type_name) do
|
148
151
|
public_name
|
149
152
|
end
|
@@ -190,31 +193,40 @@ module CTioga2
|
|
190
193
|
# function that can take advantage of a few general features. It
|
191
194
|
# is recommanded to define a #string_to_type_internal function
|
192
195
|
# rather to redefine #string_to_type
|
193
|
-
def string_to_type(string)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
196
|
+
def string_to_type(string, tn = nil)
|
197
|
+
begin
|
198
|
+
# First, passthrough
|
199
|
+
if @passthrough && @passthrough === string
|
200
|
+
return stt_run_hook(string)
|
201
|
+
end
|
202
|
+
# First, shortcuts:
|
203
|
+
if @shortcuts and @shortcuts.key? string
|
204
|
+
return stt_run_hook(@shortcuts[string])
|
205
|
+
end
|
206
|
+
if @re_shortcuts
|
207
|
+
for k, v in @re_shortcuts
|
208
|
+
if string =~ k
|
209
|
+
return stt_run_hook(v)
|
210
|
+
end
|
206
211
|
end
|
207
212
|
end
|
208
|
-
end
|
209
213
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
214
|
+
# Then, constants lookup.
|
215
|
+
if @type.key?(:namespace)
|
216
|
+
begin
|
217
|
+
return stt_run_hook(lookup_const(string))
|
218
|
+
rescue IncorrectInput
|
219
|
+
end
|
215
220
|
end
|
221
|
+
return stt_run_hook(string_to_type_internal(string))
|
222
|
+
rescue Exception => e
|
223
|
+
txt = if tn
|
224
|
+
"to type '#{tn}' failed:\n\t -> "
|
225
|
+
else
|
226
|
+
"failed: "
|
227
|
+
end
|
228
|
+
raise "Conversion of '#{string}' #{txt}#{e.message}"
|
216
229
|
end
|
217
|
-
return stt_run_hook(string_to_type_internal(string))
|
218
230
|
end
|
219
231
|
|
220
232
|
# This function does the exact opposite of the #string_to_type
|
@@ -34,7 +34,7 @@ module CTioga2
|
|
34
34
|
return 'text'
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def string_to_type_internal(str)
|
38
38
|
return str
|
39
39
|
end
|
40
40
|
end
|
@@ -67,7 +67,7 @@ module CTioga2
|
|
67
67
|
return 'regexp'
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
70
|
+
def string_to_type_internal(str)
|
71
71
|
if str =~ /^\/(.*)\/$/
|
72
72
|
return Regexp.new($1)
|
73
73
|
else
|