ctioga2 0.4 → 0.5

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.
Files changed (43) hide show
  1. data/Changelog +16 -0
  2. data/lib/ctioga2/commands/arguments.rb +5 -2
  3. data/lib/ctioga2/commands/commands.rb +45 -13
  4. data/lib/ctioga2/commands/context.rb +9 -1
  5. data/lib/ctioga2/commands/doc/help.rb +2 -2
  6. data/lib/ctioga2/commands/doc/html.rb +8 -8
  7. data/lib/ctioga2/commands/doc/introspection.rb +7 -5
  8. data/lib/ctioga2/commands/parsers/file.rb +123 -120
  9. data/lib/ctioga2/commands/parsers/old-file.rb +191 -0
  10. data/lib/ctioga2/commands/strings.rb +2 -2
  11. data/lib/ctioga2/data/datacolumn.rb +5 -2
  12. data/lib/ctioga2/data/dataset.rb +3 -13
  13. data/lib/ctioga2/data/indexed-dtable.rb +43 -11
  14. data/lib/ctioga2/data/stack.rb +65 -8
  15. data/lib/ctioga2/graphics/elements.rb +2 -1
  16. data/lib/ctioga2/graphics/elements/containers.rb +22 -3
  17. data/lib/ctioga2/graphics/elements/primitive.rb +5 -5
  18. data/lib/ctioga2/graphics/elements/xyz-contour.rb +123 -0
  19. data/lib/ctioga2/graphics/generator.rb +31 -5
  20. data/lib/ctioga2/graphics/legends.rb +44 -3
  21. data/lib/ctioga2/graphics/legends/area.rb +28 -9
  22. data/lib/ctioga2/graphics/legends/items.rb +34 -23
  23. data/lib/ctioga2/graphics/legends/multicols.rb +132 -0
  24. data/lib/ctioga2/graphics/styles.rb +3 -1
  25. data/lib/ctioga2/graphics/styles/axes.rb +10 -4
  26. data/lib/ctioga2/graphics/styles/base.rb +65 -11
  27. data/lib/ctioga2/graphics/styles/colormap.rb +2 -1
  28. data/lib/ctioga2/graphics/styles/contour.rb +141 -0
  29. data/lib/ctioga2/graphics/styles/curve.rb +49 -67
  30. data/lib/ctioga2/graphics/styles/drawable.rb +17 -8
  31. data/lib/ctioga2/graphics/styles/factory.rb +79 -38
  32. data/lib/ctioga2/graphics/styles/legend.rb +49 -6
  33. data/lib/ctioga2/graphics/styles/plot.rb +10 -9
  34. data/lib/ctioga2/graphics/styles/sheet.rb +11 -11
  35. data/lib/ctioga2/graphics/styles/texts.rb +38 -9
  36. data/lib/ctioga2/graphics/types.rb +20 -1
  37. data/lib/ctioga2/graphics/types/dimensions.rb +7 -1
  38. data/lib/ctioga2/metabuilder/types/lists.rb +4 -4
  39. data/lib/ctioga2/metabuilder/types/numbers.rb +3 -3
  40. data/lib/ctioga2/metabuilder/types/styles.rb +2 -2
  41. data/lib/ctioga2/plotmaker.rb +12 -1
  42. data/lib/ctioga2/utils.rb +27 -3
  43. metadata +8 -4
@@ -0,0 +1,191 @@
1
+ # old-file.rb: a file parser for ctioga2
2
+ # copyright (c) 2009, 2013 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 'stringio'
15
+ require 'ctioga2/utils'
16
+ require 'ctioga2/log'
17
+ require 'ctioga2/commands/commands'
18
+ require 'ctioga2/commands/strings'
19
+
20
+ module CTioga2
21
+
22
+ Version::register_svn_info('$Revision: 392 $', '$Date: 2013-06-23 01:05:02 +0200 (Sun, 23 Jun 2013) $')
23
+
24
+ module Commands
25
+
26
+ module Parsers
27
+
28
+ # Raised when EOF is encountered during a symbol parsing
29
+ class UnterminatedSymbol < Exception
30
+ end
31
+
32
+ # Unexepected character.
33
+ class UnexpectedCharacter < Exception
34
+ end
35
+
36
+ # Syntax error
37
+ class ParserSyntaxError < Exception
38
+ end
39
+
40
+ # This class is in charge of parsing a "old style" command file.
41
+ class OldFileParser
42
+
43
+ include Log
44
+
45
+ # Runs a command file targeting the given _interpreter_.
46
+ def self.run_command_file(file, interpreter)
47
+ OldFileParser.new.run_command_file(file, interpreter)
48
+ end
49
+
50
+ # Runs the given command strings
51
+ def self.run_commands(strings, interpreter)
52
+ OldFileParser.new.run_commands(strings, interpreter)
53
+ end
54
+
55
+ # Runs a command file targeting the given _interpreter_.
56
+ def run_command_file(file, interpreter)
57
+ f = open(file)
58
+ parse_io_object(f, interpreter)
59
+ end
60
+
61
+ # Runs the given command strings
62
+ def run_commands(strings, interpreter)
63
+ io = StringIO.new(strings)
64
+ parse_io_object(io, interpreter)
65
+ end
66
+
67
+ # Parses a given _io_ object, sending commands/variable
68
+ # definitions to the given _interpreter_.
69
+ def parse_io_object(io, interpreter)
70
+ # The process is simple: we look for symbols and
71
+ # corresponding syntax element: parentheses or assignments
72
+
73
+ ## @todo It would be really great if assignments could be
74
+ ## made conditional (a bit like in makefiles)
75
+ while(1)
76
+ symbol = up_to_next_symbol(io)
77
+ break if not symbol
78
+
79
+ while(1)
80
+ c = io.getc
81
+ if ! c # EOF
82
+ raise ParserSyntaxError, "Expecting something after symbol #{symbol}"
83
+ end
84
+ ch = c.chr
85
+ if ch =~ /\s/ # blank...
86
+ next
87
+ elsif ch == '(' # beginning of a function call
88
+ # Parse string:
89
+ str = InterpreterString.parse_until_unquoted(io,")")
90
+ # Now, we need to split str.
91
+ args = str.expand_and_split(/\s*,\s*/, interpreter)
92
+
93
+ cmd = interpreter.get_command(symbol)
94
+ real_args = args.slice!(0, cmd.argument_number)
95
+ # And now the options:
96
+ options = {}
97
+
98
+ # Problem: the space on the right of the = sign is
99
+ # *significant*.
100
+ for o in args
101
+ if o =~ /^\s*\/?([\w-]+)\s*=(.*)/
102
+ if cmd.has_option? $1
103
+ options[$1] = $2
104
+ else
105
+ error {
106
+ "Command #{cmd.name} does not take option #{$1}"
107
+ }
108
+ end
109
+ end
110
+ end
111
+
112
+ interpreter.context.parsing_file(symbol, io) # Missing line number
113
+ interpreter.run_command(cmd, real_args, options)
114
+ io.getc # Slurp up the )
115
+ break
116
+ elsif ch == ':' # Assignment
117
+ c = io.getc
118
+ if ! c # EOF
119
+ raise ParserSyntaxError, "Expecting = after :"
120
+ end
121
+ ch = c.chr
122
+ if ch != '='
123
+ raise ParserSyntaxError, "Expecting = after :"
124
+ end
125
+ str = InterpreterString.parse_until_unquoted(io,"\n", false)
126
+ interpreter.variables.define_variable(symbol, str,
127
+ interpreter)
128
+ break
129
+ elsif ch == '='
130
+ str = InterpreterString.parse_until_unquoted(io,"\n", false)
131
+ interpreter.variables.define_variable(symbol, str, nil)
132
+ break
133
+ else
134
+ raise UnexpectedCharacter, "Did not expect #{ch} after #{symbol}"
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ protected
141
+
142
+ SYMBOL_CHAR_REGEX = /[a-zA-Z0-9_-]/
143
+
144
+ # Parses the _io_ stream up to and including the next
145
+ # symbol. Only white space or comments may be found on the
146
+ # way. This function returns the symbol.
147
+ #
148
+ # Symbols are composed of the alphabet SYMBOL_CHAR_REGEX.
149
+ def up_to_next_symbol(io)
150
+
151
+ symbol = nil # As long as no symbol as been started
152
+ # it will stay nil.
153
+ while(1)
154
+ c = io.getc
155
+ if ! c # EOF
156
+ if symbol
157
+ raise UnterminatedSymbol, "EOF reached during symbol parsing"
158
+ else
159
+ # File is finished and we didn't meet any symbol.
160
+ # Nothing to do !
161
+ return nil
162
+ end
163
+ end
164
+ ch = c.chr
165
+ if symbol # We have started
166
+ if ch =~ SYMBOL_CHAR_REGEX
167
+ symbol += ch
168
+ else
169
+ io.ungetc(c)
170
+ return symbol
171
+ end
172
+ else
173
+ if ch =~ SYMBOL_CHAR_REGEX
174
+ symbol = ch
175
+ elsif ch =~ /\s/
176
+ # Nothing
177
+ elsif ch == '#'
178
+ io.gets
179
+ else
180
+ raise UnexpectedCharacter, "Unexpected character: #{ch}, when looking for a symbol"
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+ end
190
+ end
191
+
@@ -16,7 +16,7 @@ require 'stringio' # For debugging purposes
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 2 $', '$Date: 2009-04-25 14:03:30 +0200 (Sat, 25 Apr 2009) $')
19
+ Version::register_svn_info('$Revision: 400 $', '$Date: 2013-08-19 17:29:57 +0200 (Mon, 19 Aug 2013) $')
20
20
 
21
21
  module Commands
22
22
 
@@ -256,7 +256,7 @@ module CTioga2
256
256
  cur_str += value
257
257
  when :unquoted
258
258
  tmp = value.split(re, -1)
259
- cur_str += tmp[0]
259
+ cur_str += tmp[0] if tmp.size > 0
260
260
  # Push splitted stuff here:
261
261
  while tmp.size > 1
262
262
  retval << cur_str
@@ -17,7 +17,7 @@ require 'ctioga2/utils'
17
17
  # This module contains all the classes used by ctioga
18
18
  module CTioga2
19
19
 
20
- Version::register_svn_info('$Revision: 229 $', '$Date: 2011-01-17 17:34:57 +0100 (Mon, 17 Jan 2011) $')
20
+ Version::register_svn_info('$Revision: 402 $', '$Date: 2013-08-19 17:30:02 +0200 (Mon, 19 Aug 2013) $')
21
21
 
22
22
  module Data
23
23
 
@@ -204,7 +204,7 @@ module CTioga2
204
204
  set_vectors(new_vects)
205
205
  end
206
206
 
207
- ColumnSpecsRE = /|min|max|err/i
207
+ ColumnSpecsRE = /|min|max|err|rerr/i
208
208
 
209
209
  # This function sets the value of the DataColumn object
210
210
  # according to a hash: _spec_ => _vector_. _spec_ can be any of:
@@ -232,6 +232,9 @@ module CTioga2
232
232
  when /^err$/i
233
233
  @min_values = @values - s[key]
234
234
  @max_values = @values + s[key]
235
+ when /^rerr$/i
236
+ @min_values = @values *(1 - s[key])
237
+ @max_values = @values *(1 + s[key])
235
238
  else
236
239
  raise "Unkown key: #{key}"
237
240
  end
@@ -18,7 +18,7 @@ require 'ctioga2/data/indexed-dtable'
18
18
 
19
19
  module CTioga2
20
20
 
21
- Version::register_svn_info('$Revision: 304 $', '$Date: 2012-01-03 15:06:33 +0100 (Tue, 03 Jan 2012) $')
21
+ Version::register_svn_info('$Revision: 406 $', '$Date: 2013-08-22 21:23:44 +0200 (Thu, 22 Aug 2013) $')
22
22
 
23
23
 
24
24
  # \todo now, port the backend infrastructure...
@@ -393,18 +393,8 @@ module CTioga2
393
393
  #
394
394
  # @todo add algorithm
395
395
  def make_contour(level)
396
- dtable = indexed_table
397
- x,y,gaps = *dtable.make_contour(level)
398
-
399
- # We remove any gap corresponding to the element size,
400
- # meaningless.
401
- gaps -= [x.size]
402
- n = 0.0/0.0
403
- gaps.sort.reverse.each do |i|
404
- x.insert(i,n)
405
- y.insert(i,n)
406
- end
407
- return Dobjects::Function.new(x,y)
396
+ table = indexed_table
397
+ return table.make_contour(level, {'ret' => 'func'} )
408
398
  end
409
399
 
410
400
  # Smooths the data using a naive gaussian-like convolution (but
@@ -15,7 +15,7 @@ require 'ctioga2/utils'
15
15
 
16
16
  module CTioga2
17
17
 
18
- Version::register_svn_info('$Revision: 181 $', '$Date: 2010-10-27 15:18:35 +0200 (Wed, 27 Oct 2010) $')
18
+ Version::register_svn_info('$Revision: 406 $', '$Date: 2013-08-22 21:23:44 +0200 (Thu, 22 Aug 2013) $')
19
19
 
20
20
 
21
21
  module Data
@@ -114,19 +114,51 @@ module CTioga2
114
114
  return @y_values.size
115
115
  end
116
116
 
117
- # Returns a [xs, ys, gaps] triplet suitable for use with
118
- # t.append_points_with_gaps_to_path to show the given level.
117
+ # Makes a contour using the given level.
119
118
  #
120
- # @todo add algorithm choice too
121
- def make_contour(level)
119
+ # Depending on the value of opts['ret'], what is returned is:
120
+ # * if 'xyg', [xs, ys, gaps] triplet suitable for use with
121
+ # t.append_points_with_gaps_to_path to show the
122
+ # given level (default)
123
+ # * if 'func', a single function with nans inserted
124
+ # at the position of the gaps
125
+ # * if 'funcs', a function for each of the "continuous" segments
126
+ #
127
+ # Anything else in opts is given directly to make_contour
128
+ def make_contour(level, opts = {})
122
129
  gaps = []
123
130
  # Requires Tioga r598
124
- xs, ys = *Tioga::FigureMaker.make_contour('data' => @table,
125
- 'xs' => @x_values,
126
- 'ys' => @y_values,
127
- 'gaps' => gaps,
128
- 'level' => level)
129
- return [xs, ys, gaps]
131
+ opts = {'data' => @table,
132
+ 'xs' => @x_values,
133
+ 'ys' => @y_values,
134
+ 'gaps' => gaps,
135
+ 'level' => level
136
+ }.update(opts)
137
+
138
+ ret = opts['ret'] || 'xyg'
139
+
140
+ opts.delete('ret')
141
+ xs, ys = *Tioga::FigureMaker.make_contour(opts)
142
+
143
+ if ret == 'xyg'
144
+ return [xs, ys, gaps]
145
+ end
146
+
147
+ gaps = opts['gaps'].dup
148
+
149
+ gaps -= [xs.size]
150
+ n = 0.0/0.0
151
+ gaps.sort.reverse.each do |i|
152
+ xs.insert(i,n)
153
+ ys.insert(i,n)
154
+ end
155
+
156
+ fnc = Dobjects::Function.new(xs,ys)
157
+ if ret == 'func'
158
+ return fnc
159
+ else
160
+ return fnc.split_on_nan(:x)
161
+ end
130
162
  end
131
163
 
132
164
  end
@@ -25,7 +25,7 @@ require 'ctioga2/data/filters'
25
25
  # This module contains all the classes used by ctioga
26
26
  module CTioga2
27
27
 
28
- Version::register_svn_info('$Revision: 367 $', '$Date: 2012-12-28 16:14:52 +0100 (Fri, 28 Dec 2012) $')
28
+ Version::register_svn_info('$Revision: 390 $', '$Date: 2013-03-13 11:36:47 +0100 (Wed, 13 Mar 2013) $')
29
29
 
30
30
 
31
31
  module Data
@@ -121,28 +121,54 @@ module CTioga2
121
121
  # Returns the stored dataset, either using its index in the
122
122
  # stack, or its name in the dataset.
123
123
  def stored_dataset(spec)
124
+ return dataset_xref(spec)[0]
125
+ end
126
+
127
+
128
+ # Returns the [dataset, index, name] of the given dataset
129
+ def dataset_xref(spec)
130
+ ds = nil
131
+ index = nil
132
+ name = nil
124
133
  if spec.is_a? Numeric or spec =~ /^\s*-?\d+\s*$/
125
134
  spec = spec.to_i
126
- return @stack[spec]
135
+ index = spec
136
+ name = nil
137
+ ds = @stack[index]
138
+ for k,v in @named_datasets
139
+ if v == ds
140
+ name = k
141
+ end
142
+ end
127
143
  else
128
144
  if @named_datasets.key? spec
129
- return @named_datasets[spec]
145
+ name = spec
146
+ ds = @named_datasets[spec]
147
+ i = 0
148
+ for d in @stack
149
+ if d == ds
150
+ index = i
151
+ end
152
+ i += 1
153
+ end
130
154
  else
131
155
  raise "Unkown named dataset from the stack: '#{spec}'"
132
156
  end
133
157
  end
158
+ return [ds, index, name]
134
159
  end
135
160
 
136
161
  # Gets a dataset from the given _options_ hash. If a 'which' key
137
162
  # is present, it is used as an argument for #stored_dataset;
138
163
  # else, -1 is used.
139
- def specified_dataset(options)
164
+ def specified_dataset(options, full = false)
140
165
  spec = if options && options['which']
141
166
  options['which']
142
167
  else
143
168
  -1
144
169
  end
145
- return stored_dataset(spec)
170
+ xr = dataset_xref(spec)
171
+ return (full ? xr : xr[0])
146
172
  end
147
173
 
148
174
  # Adds a Dataset object onto the stack, running hooks if
@@ -250,11 +276,25 @@ module CTioga2
250
276
 
251
277
  pref = sprintf("#%-2d %-3d:", i, - @stack.size + i)
252
278
 
253
- STDERR.puts " * #{pref} #{ds.name} -- #{ds.ys.size + 1} columns #{name}"
279
+ STDERR.puts " * #{pref} #{ds.name} -- #{ds.ys.size + 1} columns, #{ds.x.size} points #{name}"
254
280
  i += 1
255
281
  end
256
282
  end
257
283
 
284
+ # Drops the dataset corresponding to the given spec from the
285
+ # stack
286
+ def drop_from_stack(spec)
287
+ xr = dataset_xref(spec)
288
+ if xr[1] # But that should always be the case ?
289
+ @stack.delete_at(xr[1])
290
+ else
291
+ warn { "For some reason, dataset '#{spec}' is not in the stack !"}
292
+ end
293
+ if xr[2]
294
+ @named_datasets.delete(xr[2])
295
+ end
296
+ end
297
+
258
298
 
259
299
  end
260
300
 
@@ -332,6 +372,23 @@ EOH
332
372
  <<EOH, DataStackGroup)
333
373
  Prints to standard output data contained in the last dataset pushed
334
374
  onto the stack, or the given stored dataset if the which option is given.
375
+ EOH
376
+
377
+
378
+ DropCommand =
379
+ Cmd.new("drop", nil, "--drop",
380
+ [CmdArg.new('stored-dataset')], { }) do |plotmaker,spec,opts|
381
+ plotmaker.data_stack.drop_from_stack(spec)
382
+ end
383
+
384
+ DropCommand.describe("Drops the given dataset from the stack",
385
+ <<EOH, DataStackGroup)
386
+ Removes the given dataset from the stack.
387
+
388
+ Can become useful when dealing with large datasets, some of which are
389
+ only used as intermediates for {command: apply-formula} or
390
+ {command: compute-contour}, for instance.
391
+
335
392
  EOH
336
393
 
337
394
  ConcatLastCommand =
@@ -409,8 +466,8 @@ default the one before the last) into the last one. Data points that
409
466
  have no corresponding X value in the current dataset are simply
410
467
  ignored.
411
468
 
412
- This can be used to build 3D datasets for {cmd: xyz-map} or
413
- {cmd: xy-parametric}.
469
+ This can be used to build 3D datasets for {command: xyz-map} or
470
+ {command: xy-parametric}.
414
471
  EOH
415
472
 
416
473
  XYReglinCommand =