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.
- data/COPYING +339 -0
- data/Changelog +6 -0
- data/bin/ctioga2 +26 -0
- data/lib/ctioga2/commands/arguments.rb +58 -0
- data/lib/ctioga2/commands/commands.rb +258 -0
- data/lib/ctioga2/commands/doc/doc.rb +118 -0
- data/lib/ctioga2/commands/doc/documentation-commands.rb +119 -0
- data/lib/ctioga2/commands/doc/help.rb +95 -0
- data/lib/ctioga2/commands/doc/html.rb +230 -0
- data/lib/ctioga2/commands/doc/introspection.rb +211 -0
- data/lib/ctioga2/commands/doc/man.rb +279 -0
- data/lib/ctioga2/commands/doc/markup.rb +359 -0
- data/lib/ctioga2/commands/general-commands.rb +119 -0
- data/lib/ctioga2/commands/general-types.rb +118 -0
- data/lib/ctioga2/commands/groups.rb +73 -0
- data/lib/ctioga2/commands/interpreter.rb +257 -0
- data/lib/ctioga2/commands/parsers/command-line.rb +187 -0
- data/lib/ctioga2/commands/parsers/file.rb +186 -0
- data/lib/ctioga2/commands/strings.rb +303 -0
- data/lib/ctioga2/commands/type.rb +100 -0
- data/lib/ctioga2/commands/variables.rb +101 -0
- data/lib/ctioga2/data/backends/backend.rb +260 -0
- data/lib/ctioga2/data/backends/backends.rb +39 -0
- data/lib/ctioga2/data/backends/backends/gnuplot.rb +140 -0
- data/lib/ctioga2/data/backends/backends/math.rb +121 -0
- data/lib/ctioga2/data/backends/backends/text.rb +335 -0
- data/lib/ctioga2/data/backends/description.rb +405 -0
- data/lib/ctioga2/data/backends/factory.rb +73 -0
- data/lib/ctioga2/data/backends/parameter.rb +109 -0
- data/lib/ctioga2/data/datacolumn.rb +245 -0
- data/lib/ctioga2/data/dataset.rb +233 -0
- data/lib/ctioga2/data/filters.rb +131 -0
- data/lib/ctioga2/data/merge.rb +43 -0
- data/lib/ctioga2/data/point.rb +72 -0
- data/lib/ctioga2/data/stack.rb +294 -0
- data/lib/ctioga2/graphics/coordinates.rb +73 -0
- data/lib/ctioga2/graphics/elements.rb +111 -0
- data/lib/ctioga2/graphics/elements/containers.rb +111 -0
- data/lib/ctioga2/graphics/elements/curve2d.rb +155 -0
- data/lib/ctioga2/graphics/elements/element.rb +90 -0
- data/lib/ctioga2/graphics/elements/primitive.rb +256 -0
- data/lib/ctioga2/graphics/elements/subplot.rb +140 -0
- data/lib/ctioga2/graphics/generator.rb +68 -0
- data/lib/ctioga2/graphics/legends.rb +108 -0
- data/lib/ctioga2/graphics/legends/area.rb +199 -0
- data/lib/ctioga2/graphics/legends/items.rb +183 -0
- data/lib/ctioga2/graphics/legends/provider.rb +58 -0
- data/lib/ctioga2/graphics/legends/storage.rb +65 -0
- data/lib/ctioga2/graphics/root.rb +209 -0
- data/lib/ctioga2/graphics/styles.rb +30 -0
- data/lib/ctioga2/graphics/styles/axes.rb +247 -0
- data/lib/ctioga2/graphics/styles/background.rb +122 -0
- data/lib/ctioga2/graphics/styles/base.rb +115 -0
- data/lib/ctioga2/graphics/styles/carrays.rb +53 -0
- data/lib/ctioga2/graphics/styles/curve.rb +101 -0
- data/lib/ctioga2/graphics/styles/drawable.rb +87 -0
- data/lib/ctioga2/graphics/styles/factory.rb +351 -0
- data/lib/ctioga2/graphics/styles/legend.rb +63 -0
- data/lib/ctioga2/graphics/styles/plot.rb +410 -0
- data/lib/ctioga2/graphics/styles/sets.rb +64 -0
- data/lib/ctioga2/graphics/styles/texts.rb +277 -0
- data/lib/ctioga2/graphics/subplot-commands.rb +141 -0
- data/lib/ctioga2/graphics/types.rb +188 -0
- data/lib/ctioga2/graphics/types/bijection.rb +79 -0
- data/lib/ctioga2/graphics/types/boundaries.rb +170 -0
- data/lib/ctioga2/graphics/types/boxes.rb +157 -0
- data/lib/ctioga2/graphics/types/dimensions.rb +157 -0
- data/lib/ctioga2/graphics/types/point.rb +247 -0
- data/lib/ctioga2/log.rb +97 -0
- data/lib/ctioga2/metabuilder/type.rb +316 -0
- data/lib/ctioga2/metabuilder/types.rb +39 -0
- data/lib/ctioga2/metabuilder/types/coordinates.rb +124 -0
- data/lib/ctioga2/metabuilder/types/dates.rb +43 -0
- data/lib/ctioga2/metabuilder/types/lists.rb +188 -0
- data/lib/ctioga2/metabuilder/types/numbers.rb +97 -0
- data/lib/ctioga2/metabuilder/types/strings.rb +93 -0
- data/lib/ctioga2/metabuilder/types/styles.rb +178 -0
- data/lib/ctioga2/plotmaker.rb +677 -0
- data/lib/ctioga2/postprocess.rb +115 -0
- data/lib/ctioga2/utils.rb +120 -0
- data/setup.rb +1586 -0
- 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
|
+
|