ctioga2 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.
Files changed (82) hide show
  1. data/COPYING +339 -0
  2. data/Changelog +6 -0
  3. data/bin/ctioga2 +26 -0
  4. data/lib/ctioga2/commands/arguments.rb +58 -0
  5. data/lib/ctioga2/commands/commands.rb +258 -0
  6. data/lib/ctioga2/commands/doc/doc.rb +118 -0
  7. data/lib/ctioga2/commands/doc/documentation-commands.rb +119 -0
  8. data/lib/ctioga2/commands/doc/help.rb +95 -0
  9. data/lib/ctioga2/commands/doc/html.rb +230 -0
  10. data/lib/ctioga2/commands/doc/introspection.rb +211 -0
  11. data/lib/ctioga2/commands/doc/man.rb +279 -0
  12. data/lib/ctioga2/commands/doc/markup.rb +359 -0
  13. data/lib/ctioga2/commands/general-commands.rb +119 -0
  14. data/lib/ctioga2/commands/general-types.rb +118 -0
  15. data/lib/ctioga2/commands/groups.rb +73 -0
  16. data/lib/ctioga2/commands/interpreter.rb +257 -0
  17. data/lib/ctioga2/commands/parsers/command-line.rb +187 -0
  18. data/lib/ctioga2/commands/parsers/file.rb +186 -0
  19. data/lib/ctioga2/commands/strings.rb +303 -0
  20. data/lib/ctioga2/commands/type.rb +100 -0
  21. data/lib/ctioga2/commands/variables.rb +101 -0
  22. data/lib/ctioga2/data/backends/backend.rb +260 -0
  23. data/lib/ctioga2/data/backends/backends.rb +39 -0
  24. data/lib/ctioga2/data/backends/backends/gnuplot.rb +140 -0
  25. data/lib/ctioga2/data/backends/backends/math.rb +121 -0
  26. data/lib/ctioga2/data/backends/backends/text.rb +335 -0
  27. data/lib/ctioga2/data/backends/description.rb +405 -0
  28. data/lib/ctioga2/data/backends/factory.rb +73 -0
  29. data/lib/ctioga2/data/backends/parameter.rb +109 -0
  30. data/lib/ctioga2/data/datacolumn.rb +245 -0
  31. data/lib/ctioga2/data/dataset.rb +233 -0
  32. data/lib/ctioga2/data/filters.rb +131 -0
  33. data/lib/ctioga2/data/merge.rb +43 -0
  34. data/lib/ctioga2/data/point.rb +72 -0
  35. data/lib/ctioga2/data/stack.rb +294 -0
  36. data/lib/ctioga2/graphics/coordinates.rb +73 -0
  37. data/lib/ctioga2/graphics/elements.rb +111 -0
  38. data/lib/ctioga2/graphics/elements/containers.rb +111 -0
  39. data/lib/ctioga2/graphics/elements/curve2d.rb +155 -0
  40. data/lib/ctioga2/graphics/elements/element.rb +90 -0
  41. data/lib/ctioga2/graphics/elements/primitive.rb +256 -0
  42. data/lib/ctioga2/graphics/elements/subplot.rb +140 -0
  43. data/lib/ctioga2/graphics/generator.rb +68 -0
  44. data/lib/ctioga2/graphics/legends.rb +108 -0
  45. data/lib/ctioga2/graphics/legends/area.rb +199 -0
  46. data/lib/ctioga2/graphics/legends/items.rb +183 -0
  47. data/lib/ctioga2/graphics/legends/provider.rb +58 -0
  48. data/lib/ctioga2/graphics/legends/storage.rb +65 -0
  49. data/lib/ctioga2/graphics/root.rb +209 -0
  50. data/lib/ctioga2/graphics/styles.rb +30 -0
  51. data/lib/ctioga2/graphics/styles/axes.rb +247 -0
  52. data/lib/ctioga2/graphics/styles/background.rb +122 -0
  53. data/lib/ctioga2/graphics/styles/base.rb +115 -0
  54. data/lib/ctioga2/graphics/styles/carrays.rb +53 -0
  55. data/lib/ctioga2/graphics/styles/curve.rb +101 -0
  56. data/lib/ctioga2/graphics/styles/drawable.rb +87 -0
  57. data/lib/ctioga2/graphics/styles/factory.rb +351 -0
  58. data/lib/ctioga2/graphics/styles/legend.rb +63 -0
  59. data/lib/ctioga2/graphics/styles/plot.rb +410 -0
  60. data/lib/ctioga2/graphics/styles/sets.rb +64 -0
  61. data/lib/ctioga2/graphics/styles/texts.rb +277 -0
  62. data/lib/ctioga2/graphics/subplot-commands.rb +141 -0
  63. data/lib/ctioga2/graphics/types.rb +188 -0
  64. data/lib/ctioga2/graphics/types/bijection.rb +79 -0
  65. data/lib/ctioga2/graphics/types/boundaries.rb +170 -0
  66. data/lib/ctioga2/graphics/types/boxes.rb +157 -0
  67. data/lib/ctioga2/graphics/types/dimensions.rb +157 -0
  68. data/lib/ctioga2/graphics/types/point.rb +247 -0
  69. data/lib/ctioga2/log.rb +97 -0
  70. data/lib/ctioga2/metabuilder/type.rb +316 -0
  71. data/lib/ctioga2/metabuilder/types.rb +39 -0
  72. data/lib/ctioga2/metabuilder/types/coordinates.rb +124 -0
  73. data/lib/ctioga2/metabuilder/types/dates.rb +43 -0
  74. data/lib/ctioga2/metabuilder/types/lists.rb +188 -0
  75. data/lib/ctioga2/metabuilder/types/numbers.rb +97 -0
  76. data/lib/ctioga2/metabuilder/types/strings.rb +93 -0
  77. data/lib/ctioga2/metabuilder/types/styles.rb +178 -0
  78. data/lib/ctioga2/plotmaker.rb +677 -0
  79. data/lib/ctioga2/postprocess.rb +115 -0
  80. data/lib/ctioga2/utils.rb +120 -0
  81. data/setup.rb +1586 -0
  82. metadata +144 -0
@@ -0,0 +1,109 @@
1
+ # parameter.rb : A class to describe a parameter
2
+ # Copyright (C) 2006 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.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
+
18
+ require 'ctioga2/utils'
19
+
20
+ require 'ctioga2/metabuilder/type'
21
+
22
+ module CTioga2
23
+
24
+ Version::register_svn_info('$Revision: 17 $', '$Date: 2009-04-28 22:22:22 +0200 (Tue, 28 Apr 2009) $')
25
+
26
+ module Data
27
+
28
+ module Backends
29
+
30
+ # A parameter describes a way of storing some information into an
31
+ # instance of an object. No type checking is done on the target object
32
+ # when the actual reading/writing is done. However, the type checking
33
+ # is done upstream by the Description system.
34
+ #
35
+ # A Parameter consists of several things:
36
+ #
37
+ # * a #name, to identify it in a unique fashion;
38
+ # * a #type, used to convert to and from String and for user
39
+ # interaction in general;
40
+ # * some explanative text, used to inform the user: #long_name and
41
+ # #description
42
+ # * two symbols that are used to gain read and write access of the
43
+ # parameter on the target object.
44
+ #
45
+ # The Parameter class can be used to maintain a set of
46
+ # meta-informations about types in a given object.
47
+ class Parameter
48
+
49
+ # The short name of the parameter
50
+ attr_accessor :name
51
+
52
+ # The long name of the parameter, to be translated
53
+ attr_accessor :long_name
54
+
55
+ # The function names that should be used to set the symbol and
56
+ # retrieve it's current value. The corresponding functions should
57
+ # read or return a string, and writer(reader) should be a noop.
58
+ attr_accessor :reader_symbol, :writer_symbol
59
+
60
+ # The (text) description of the parameter
61
+ attr_accessor :description
62
+
63
+ # The actual Commands::CommandType of the parameter
64
+ attr_accessor :type
65
+
66
+ # Creates a new Parameter with the given symbols. Remember that
67
+ # if you don't intend to use #get, #get_raw, #set and #set_raw,
68
+ # you don't need to pass meaningful values to _writer_symbol_ and
69
+ # _reader_symbol_.
70
+ def initialize(name, writer_symbol,
71
+ reader_symbol,
72
+ long_name, type,
73
+ description)
74
+ @name = name
75
+ @writer_symbol = writer_symbol
76
+ @reader_symbol = reader_symbol
77
+ @description = description
78
+ @long_name = long_name
79
+ @type = Commands::CommandType::get_type(type)
80
+ end
81
+
82
+
83
+ # Sets directly the target parameter, without type conversion
84
+ def set_value(target, val)
85
+ target.send(@writer_symbol, val)
86
+ end
87
+
88
+ # Uses the #writer_symbol of the _target_ to set the value of the
89
+ # parameter to the one converted from the String _str_
90
+ def set_from_string(target, str)
91
+ set_value(target, string_to_type(str))
92
+ end
93
+
94
+
95
+ # Aquires the value from the backend, and returns it in the
96
+ # form of a string
97
+ def get_string(target)
98
+ return type_to_string(get_value(target))
99
+ end
100
+
101
+ # Aquires the value from the backend, and returns it.
102
+ def get_value(target)
103
+ target.send(@reader_symbol)
104
+ end
105
+
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,245 @@
1
+ # datacolumn.rb: a class holding a 'column' of data
2
+ # copyright (c) 2009 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 'Dobjects/Dvector'
15
+ require 'ctioga2/utils'
16
+
17
+ # This module contains all the classes used by ctioga
18
+ module CTioga2
19
+
20
+ Version::register_svn_info('$Revision: 81 $', '$Date: 2009-06-11 21:14:59 +0200 (Thu, 11 Jun 2009) $')
21
+
22
+ module Data
23
+
24
+ # This class holds one column, possibly with error bars.
25
+ #
26
+ # TODO: a way to concatenate two DataColumns
27
+ #
28
+ # TODO: a way to easily access the by "lines"
29
+ class DataColumn
30
+
31
+ # A Dvector holding ``real'' values
32
+ attr_accessor :values
33
+
34
+ # A Dvector holding minimal values
35
+ attr_accessor :min_values
36
+
37
+ # A Dvector holding maximal values
38
+ attr_accessor :max_values
39
+
40
+ # TODO: a method that resembles the code in the old text backend
41
+ # to set errors according to a speficication (relative,
42
+ # absolute, already max/min)
43
+
44
+ # TODO: a dup !
45
+
46
+ def initialize(values, min = nil, max = nil)
47
+ @values = values
48
+ @min_values = min
49
+ @max_values = max
50
+ end
51
+
52
+
53
+ # Yields all the vectors in turn to apply a given
54
+ # transformation.
55
+ def apply
56
+ for v in all_vectors
57
+ yield v if v
58
+ end
59
+ end
60
+
61
+ # Sorts the values according to the index vector given.
62
+ def reindex(idx_vector)
63
+ for v in all_vectors
64
+ # This is slow !
65
+ # Code should be written in C on the dvector side.
66
+ #
67
+ # Or we could use Function.sort, though this is not very
68
+ # elegant nor efficient. (but it would be memory-efficient,
69
+ # though).
70
+ next unless v
71
+ w = Dobjects::Dvector.new(idx_vector.size) do |i|
72
+ v[idx_vector[i]]
73
+ end
74
+ v.replace(w)
75
+ end
76
+ end
77
+
78
+ # Whether there are error bars.
79
+ def has_errors?
80
+ return (@min_values && @max_values)
81
+ end
82
+
83
+ # Column names. _base_ is used as a base for the names. If
84
+ # _expand_ is on, always return all the names.
85
+ def column_names(base, expand = false)
86
+ if expand || has_errors?
87
+ return [base, "#{base}min", "#{base}max"]
88
+ else
89
+ return [base]
90
+ end
91
+ end
92
+
93
+ # Values, [value, min, max], at the given index. If #min and
94
+ # #max are nil only [value] is returned -- unless _expand_ is
95
+ # set, in which case we make up a default value for min and max.
96
+ def values_at(i, expand = false)
97
+ if has_errors?
98
+ return [@values[i], @min_values[i], @max_values[i]]
99
+ else
100
+ if expand
101
+ return [@values[i], @values[i], @values[i]]
102
+ else
103
+ return [@values[i]]
104
+ end
105
+ end
106
+ end
107
+
108
+ # Returns the number of elements.
109
+ def size
110
+ return @values.size
111
+ end
112
+
113
+ # Creates dummy errors (ie, min_values = max_values = values) if
114
+ # the datacolumn does not currently have one.
115
+ def ensure_has_errors
116
+ if ! has_errors?
117
+ @min_values = @values.dup
118
+ @max_values = @values.dup
119
+ end
120
+ end
121
+
122
+ # Concatenates with another DataColumn, making sure the errors
123
+ # and such are not lost.
124
+ def <<(column)
125
+ # If there are error bars, wew make sure we concatenate all of them
126
+ if has_errors? || column.has_errors?
127
+ self.ensure_has_errors
128
+ column.ensure_has_errors
129
+ @min_values.concat(column.min_values)
130
+ @max_values.concat(column.max_values)
131
+ end
132
+ @values.concat(column.values)
133
+ end
134
+
135
+ # Only keeps every _n_ points in the DataColumn
136
+ def trim!(nb)
137
+ nb = nb.to_i
138
+ if nb < 2
139
+ return
140
+ end
141
+
142
+ new_vects = []
143
+ for v in all_vectors
144
+ if v
145
+ new_values = Dobjects::Dvector.new
146
+ i = 0
147
+ for val in v
148
+ if (i % nb) == 0
149
+ new_values << val
150
+ end
151
+ i+=1
152
+ end
153
+ new_vects << new_values
154
+ else
155
+ new_vects << nil
156
+ end
157
+ end
158
+ set_vectors(new_vects)
159
+ end
160
+
161
+ ColumnSpecsRE = /|min|max/i
162
+
163
+ # This function sets the value of the DataColumn object
164
+ # according to a hash: _spec_ => _vector_. _spec_ can be any of:
165
+ # * 'value', 'values' or '' : the #values
166
+ # * 'min' : #min
167
+ # * 'max' : #max
168
+ def from_hash(spec)
169
+ s = spec.dup
170
+ @values = spec['value'] || spec['values'] ||
171
+ spec['']
172
+ if ! @values
173
+ raise "Need a 'value' specification"
174
+ end
175
+ for k in ['value', 'values', '']
176
+ s.delete(k)
177
+ end
178
+ for key in s.keys
179
+ case key
180
+ when /^min$/i
181
+ @min_values = s[key]
182
+ when /^max$/i
183
+ @max_values = s[key]
184
+ else
185
+ raise "Unkown key: #{key}"
186
+ end
187
+ end
188
+ end
189
+
190
+
191
+ # Creates and returns a DataColumn object according to the
192
+ # _spec_. See #from_hash for more information.
193
+ def self.from_hash(spec)
194
+ a = DataColumn.new(nil)
195
+ a.from_hash(spec)
196
+ return a
197
+ end
198
+
199
+ # Returns the minimum value of all vectors held in this column
200
+ def min
201
+ m = @values.min
202
+ for v in [@min_values, @max_values]
203
+ if v
204
+ m1 = v.min
205
+ if m1 < m # This also works if m1 is NaN
206
+ m = m1
207
+ end
208
+ end
209
+ end
210
+ return m
211
+ end
212
+
213
+ # Returns the maximum value of all vectors held in this column
214
+ def max
215
+ m = @values.max
216
+ for v in [@min_values, @max_values]
217
+ if v
218
+ m1 = v.max
219
+ if m1 > m # This also works if m1 is NaN
220
+ m = m1
221
+ end
222
+ end
223
+ end
224
+ return m
225
+ end
226
+
227
+ protected
228
+
229
+ # All the vectors held by the DataColumn
230
+ def all_vectors
231
+ return [@values, @min_values, @max_values]
232
+ end
233
+
234
+ # Sets the vectors to the given list, as might have been
235
+ # returned by #all_vectors
236
+ def set_vectors(vectors)
237
+ @values, @min_values, @max_values = *vectors
238
+ end
239
+
240
+ end
241
+
242
+ end
243
+
244
+ end
245
+
@@ -0,0 +1,233 @@
1
+ # dataset.rb: a class holding *one* dataset
2
+ # copyright (c) 2009 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/data/datacolumn'
16
+
17
+ module CTioga2
18
+
19
+ Version::register_svn_info('$Revision: 81 $', '$Date: 2009-06-11 21:14:59 +0200 (Thu, 11 Jun 2009) $')
20
+
21
+
22
+ # TODO: now, port the backend infrastructure...
23
+
24
+ # This module holds all the code that deals with manipulation and
25
+ # acquisition of data of any sort.
26
+ module Data
27
+
28
+ # This is the central class of the data manipulation in ctioga.
29
+ # It is a series of 'Y' DataColumn indexed on a unique 'X'
30
+ # DataColumn. This can be used to represent multiple XY data sets,
31
+ # but also XYZ and even more complex data. The actual
32
+ # signification of the various 'Y' columns are left to the user.
33
+ class Dataset
34
+
35
+ # The X DataColumn
36
+ attr_accessor :x
37
+
38
+ # All Y DataColumn (an Array of DataColumn)
39
+ attr_accessor :ys
40
+
41
+ # The name of the Dataset, such as one that could be used in a
42
+ # legend (like for the --auto-legend option of ctioga).
43
+ attr_accessor :name
44
+
45
+ # Creates a new Dataset object with the given data columns
46
+ # (Dvector or DataColumn). #x is the first one
47
+ def initialize(name, columns)
48
+ columns.each_index do |i|
49
+ if columns[i].is_a? Dobjects::Dvector
50
+ columns[i] = DataColumn.new(columns[i])
51
+ end
52
+ end
53
+ @x = columns[0]
54
+ @ys = columns[1..-1]
55
+ @name = name
56
+ end
57
+
58
+ # Creates a new Dataset from a specification. This function
59
+ # parses a specification in the form of:
60
+ # * a:b{:c}+
61
+ # * spec=a{:spec2=b}+
62
+ #
63
+ # It yields each of the unprocessed text, not necessarily in the
64
+ # order they were read, and expects a Dvector as a return value.
65
+ #
66
+ # It then builds a suitable Dataset object with these values,
67
+ # and returns it.
68
+ #
69
+ # It is *strongly* *recommended* to use this function for
70
+ # reimplementations of Backends::Backend#query_dataset.
71
+ def self.dataset_from_spec(name, spec)
72
+ specs = []
73
+ i = 0
74
+ for s in spec.split(/:/)
75
+ if s =~ /^(x|y\d*|z)(#{DataColumn::ColumnSpecsRE})=(.*)/i
76
+ which, mod, s = $1.downcase,($2 && $2.downcase) || "value",$3
77
+
78
+ case which
79
+ when /x/
80
+ idx = 0
81
+ when /y(\d+)?/
82
+ if $1
83
+ idx = $1.to_i
84
+ else
85
+ idx = 1
86
+ end
87
+ when /z/
88
+ idx = 2
89
+ end
90
+ specs[idx] ||= {}
91
+ specs[idx][mod] = yield s
92
+ else
93
+ specs[i] = {"value" => yield(s)}
94
+ end
95
+ i += 1
96
+ end
97
+ columns = []
98
+ for s in specs
99
+ columns << DataColumn.from_hash(s)
100
+ end
101
+ return Dataset.new(name, columns)
102
+ end
103
+
104
+ # The main Y column (ie, the first one)
105
+ def y
106
+ return @ys[0]
107
+ end
108
+
109
+ # The Z column, if applicable
110
+ def z
111
+ return @ys[1]
112
+ end
113
+
114
+ # Sorts all columns according to X values
115
+ def sort!
116
+ idx_vector = Dobjects::Dvector.new(@x.values.size) do |i|
117
+ i
118
+ end
119
+ f = Dobjects::Function.new(@x.values.dup, idx_vector)
120
+ f.sort
121
+ # Now, idx_vector contains the indices that make X values
122
+ # sorted.
123
+ for col in all_columns
124
+ col.reindex(idx_vector)
125
+ end
126
+ end
127
+
128
+ # Returns an array with Column names.
129
+ def column_names
130
+ retval = @x.column_names("x")
131
+ @ys.each_index do |i|
132
+ retval += @ys[i].column_names("y#{i+1}")
133
+ end
134
+ return retval
135
+ end
136
+
137
+ # Iterates over all the values of the Dataset
138
+ def each_values
139
+ @x.size.times do |i|
140
+ v = @x.values_at(i)
141
+ for y in @ys
142
+ v += y.values_at(i)
143
+ end
144
+ yield i, *v
145
+ end
146
+ end
147
+
148
+ # The overall number of columns
149
+ def size
150
+ return 1 + @ys.size
151
+ end
152
+
153
+ # Concatenates another Dataset to this one
154
+ def <<(dataset)
155
+ if dataset.size != self.size
156
+ raise "Can't concatenate datasets that don't have the same number of columns: #{self.size} vs #{dataset.size}"
157
+ end
158
+ @x << dataset.x
159
+ @ys.size.times do |i|
160
+ @ys[i] << dataset.ys[i]
161
+ end
162
+ end
163
+
164
+
165
+ # Trims all data columns. See DataColumn#trim!
166
+ def trim!(nb)
167
+ for col in all_columns
168
+ col.trim!(nb)
169
+ end
170
+ end
171
+
172
+
173
+ # Modifies the dataset to only keep the data for which the block
174
+ # returns true. The block should take the following arguments,
175
+ # in order:
176
+ #
177
+ # _x_, _xmin_, _xmax_, _y_, _ymin_, _ymax_, _y1_, _y1min_, _y1max_,
178
+ # _z_, _zmin_, _zmax_, _y2_, _y2min_, _y2max_, _y3_, _y3min_, _y3max_
179
+ #
180
+ def select!(&block)
181
+ target = []
182
+ @x.size.times do |i|
183
+ args = @x.values_at(i, true)
184
+ args.concat(@ys[0].values_at(i, true) * 2)
185
+ if @ys[1]
186
+ args.concat(@ys[1].values_at(i, true) * 2)
187
+ for yvect in @ys[2..-1]
188
+ args.concat(yvect.values_at(i, true))
189
+ end
190
+ end
191
+ if block.call(*args)
192
+ target << i
193
+ end
194
+ end
195
+ for col in all_columns
196
+ col.reindex(target)
197
+ end
198
+ end
199
+
200
+ # Same as #select!, but you give it a text formula instead of a
201
+ # block. It internall calls #select!, by the way ;-)...
202
+ def select_formula!(formula)
203
+ names = @x.column_names('x', true)
204
+ names.concat(@x.column_names('y', true))
205
+ names.concat(@x.column_names('y1', true))
206
+ if @ys[1]
207
+ names.concat(@x.column_names('z', true))
208
+ names.concat(@x.column_names('y2', true))
209
+ i = 3
210
+ for yvect in @ys[2..-1]
211
+ names.concat(@x.column_names("y#{i}", true))
212
+ i += 1
213
+ end
214
+ end
215
+ block = eval("proc do |#{names.join(',')}|\n#{formula}\nend")
216
+ select!(&block)
217
+ end
218
+
219
+ # TODO: a dup !
220
+
221
+ protected
222
+
223
+ # Returns all DataColumn objects held by this Dataset
224
+ def all_columns
225
+ return [@x, *@ys]
226
+ end
227
+
228
+ end
229
+
230
+ end
231
+
232
+ end
233
+