ctioga 1.11.1
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 +340 -0
- data/ctioga/bin/ctable +28 -0
- data/ctioga/bin/ctioga +37 -0
- data/ctioga/doc/ctable.1 +156 -0
- data/ctioga/doc/ctioga.1 +2363 -0
- data/ctioga/examples/README +46 -0
- data/ctioga/examples/ctioga.gnuplot +4 -0
- data/ctioga/examples/ctioga_within_tioga.rb +53 -0
- data/ctioga/examples/ctiogarc.rb +24 -0
- data/ctioga/examples/include_1.rb +15 -0
- data/ctioga/examples/noise.dat +100 -0
- data/ctioga/examples/noise.rb +13 -0
- data/ctioga/examples/trig.csv +100 -0
- data/ctioga/examples/trig.dat +100 -0
- data/ctioga/examples/trig.rb +14 -0
- data/ctioga/examples/trigh.dat +100 -0
- data/ctioga/examples/trigh.rb +10 -0
- data/ctioga/examples/tutorial +763 -0
- data/ctioga/examples/tutorial.sh +269 -0
- data/ctioga/tests/README +14 -0
- data/ctioga/tests/axes.sh +40 -0
- data/ctioga/tests/basic.sh +11 -0
- data/ctioga/tests/draw.sh +24 -0
- data/ctioga/tests/histograms.sh +14 -0
- data/ctioga/tests/insets.sh +41 -0
- data/ctioga/tests/layouts.sh +29 -0
- data/ctioga/tests/legends.sh +113 -0
- data/ctioga/tests/styles.sh +43 -0
- data/ctioga/tests/test_style.sh +8 -0
- data/ctioga/tests/tests.sh +24 -0
- data/ctioga/tests/text_backend.sh +83 -0
- data/ctioga/tests/tioga_defaults.rb +18 -0
- data/lib/CTioga/axes.rb +904 -0
- data/lib/CTioga/backends.rb +88 -0
- data/lib/CTioga/boundaries.rb +224 -0
- data/lib/CTioga/ctable.rb +134 -0
- data/lib/CTioga/curve_style.rb +246 -0
- data/lib/CTioga/debug.rb +199 -0
- data/lib/CTioga/dimension.rb +133 -0
- data/lib/CTioga/elements.rb +17 -0
- data/lib/CTioga/elements/base.rb +84 -0
- data/lib/CTioga/elements/containers.rb +578 -0
- data/lib/CTioga/elements/curves.rb +368 -0
- data/lib/CTioga/elements/tioga_primitives.rb +440 -0
- data/lib/CTioga/layout.rb +595 -0
- data/lib/CTioga/legends.rb +29 -0
- data/lib/CTioga/legends/cmdline.rb +187 -0
- data/lib/CTioga/legends/item.rb +164 -0
- data/lib/CTioga/legends/style.rb +257 -0
- data/lib/CTioga/log.rb +73 -0
- data/lib/CTioga/movingarrays.rb +131 -0
- data/lib/CTioga/partition.rb +271 -0
- data/lib/CTioga/plot_style.rb +230 -0
- data/lib/CTioga/plotmaker.rb +1677 -0
- data/lib/CTioga/shortcuts.rb +69 -0
- data/lib/CTioga/structures.rb +82 -0
- data/lib/CTioga/styles.rb +140 -0
- data/lib/CTioga/themes.rb +581 -0
- data/lib/CTioga/themes/classical.rb +82 -0
- data/lib/CTioga/themes/demo.rb +63 -0
- data/lib/CTioga/themes/fits.rb +91 -0
- data/lib/CTioga/themes/mono.rb +33 -0
- data/lib/CTioga/tioga.rb +32 -0
- data/lib/CTioga/utils.rb +173 -0
- data/lib/MetaBuilder/Parameters/dates.rb +38 -0
- data/lib/MetaBuilder/Parameters/lists.rb +132 -0
- data/lib/MetaBuilder/Parameters/numbers.rb +69 -0
- data/lib/MetaBuilder/Parameters/strings.rb +86 -0
- data/lib/MetaBuilder/Parameters/styles.rb +75 -0
- data/lib/MetaBuilder/Qt4/Parameters/dates.rb +51 -0
- data/lib/MetaBuilder/Qt4/Parameters/numbers.rb +65 -0
- data/lib/MetaBuilder/Qt4/Parameters/strings.rb +106 -0
- data/lib/MetaBuilder/Qt4/parameter.rb +172 -0
- data/lib/MetaBuilder/Qt4/parameters.rb +9 -0
- data/lib/MetaBuilder/descriptions.rb +603 -0
- data/lib/MetaBuilder/factory.rb +101 -0
- data/lib/MetaBuilder/group.rb +57 -0
- data/lib/MetaBuilder/metabuilder.rb +10 -0
- data/lib/MetaBuilder/parameter.rb +374 -0
- data/lib/MetaBuilder/parameters.rb +11 -0
- data/lib/MetaBuilder/qt4.rb +8 -0
- data/lib/SciYAG/Backends/backend.rb +379 -0
- data/lib/SciYAG/Backends/binner.rb +168 -0
- data/lib/SciYAG/Backends/cache.rb +102 -0
- data/lib/SciYAG/Backends/dataset.rb +158 -0
- data/lib/SciYAG/Backends/descriptions.rb +469 -0
- data/lib/SciYAG/Backends/filters.rb +25 -0
- data/lib/SciYAG/Backends/filters/average.rb +134 -0
- data/lib/SciYAG/Backends/filters/cumulate.rb +37 -0
- data/lib/SciYAG/Backends/filters/filter.rb +70 -0
- data/lib/SciYAG/Backends/filters/norm.rb +39 -0
- data/lib/SciYAG/Backends/filters/smooth.rb +63 -0
- data/lib/SciYAG/Backends/filters/sort.rb +43 -0
- data/lib/SciYAG/Backends/filters/strip.rb +34 -0
- data/lib/SciYAG/Backends/filters/trim.rb +64 -0
- data/lib/SciYAG/Backends/gnuplot.rb +131 -0
- data/lib/SciYAG/Backends/math.rb +108 -0
- data/lib/SciYAG/Backends/mdb.rb +462 -0
- data/lib/SciYAG/Backends/multitext.rb +96 -0
- data/lib/SciYAG/Backends/source.rb +64 -0
- data/lib/SciYAG/Backends/text.rb +339 -0
- data/lib/SciYAG/backends.rb +16 -0
- metadata +191 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# multitext.rb : A simple backend to deal with multiple basic text files.
|
|
2
|
+
# Copyright (C) 2006 Jean-Julien Fleck
|
|
3
|
+
# Directly inspired from Vincent Fourmond's text.rb
|
|
4
|
+
|
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with this program; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
require 'SciYAG/Backends/text'
|
|
22
|
+
require 'Dobjects/Dvector'
|
|
23
|
+
require 'Dobjects/Function'
|
|
24
|
+
|
|
25
|
+
module SciYAG
|
|
26
|
+
|
|
27
|
+
module Backends
|
|
28
|
+
|
|
29
|
+
class MultiTextBackend < TextBackend
|
|
30
|
+
|
|
31
|
+
include Dobjects
|
|
32
|
+
|
|
33
|
+
describe 'multitext', 'MultiText format', <<EOD
|
|
34
|
+
This backend can read multiple text files in a format close to the one
|
|
35
|
+
understood by gnuplot and the like. Allows to plot one column form one file
|
|
36
|
+
with respect to another column of another file.
|
|
37
|
+
EOD
|
|
38
|
+
|
|
39
|
+
inherit_parameters :skip
|
|
40
|
+
|
|
41
|
+
def initialize
|
|
42
|
+
@dummy = nil
|
|
43
|
+
@current = nil
|
|
44
|
+
# @current is an array of Dvectors holding the contents of the most
|
|
45
|
+
# recently read files, so that there is no need to read it again.
|
|
46
|
+
@skip = 0
|
|
47
|
+
@included_modules = [] # to make sure we give them to
|
|
48
|
+
# compute_formula
|
|
49
|
+
super()
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def extend(mod)
|
|
53
|
+
super
|
|
54
|
+
@included_modules << mod
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# This is called by the architecture to get the data. It splits
|
|
58
|
+
# the set name into filename@cols, reads the file if necessary and
|
|
59
|
+
# calls get_data
|
|
60
|
+
def query_xy_data(set)
|
|
61
|
+
cols = []
|
|
62
|
+
files= []
|
|
63
|
+
nb_match = -1
|
|
64
|
+
new_set = set.gsub(/\[(.*?)@(.*?)\]/) do |match|
|
|
65
|
+
cols.push($2)
|
|
66
|
+
files.push($1)
|
|
67
|
+
nb_match += 1
|
|
68
|
+
"column[#{nb_match}]"
|
|
69
|
+
end
|
|
70
|
+
@current = Hash.new
|
|
71
|
+
files.uniq.each do |file|
|
|
72
|
+
@current[file] = Dvector.fancy_read(file, nil,
|
|
73
|
+
'index_col' => true,
|
|
74
|
+
'skip_first' => @skip)
|
|
75
|
+
end
|
|
76
|
+
return Function.new(*get_data(cols,files,new_set))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Reads the data using the columns specification, provided that
|
|
80
|
+
# the appropriate files have already been loaded into @current. For now
|
|
81
|
+
# no single sanity check.
|
|
82
|
+
def get_data(cols,files,set)
|
|
83
|
+
vectors = []
|
|
84
|
+
cols.each_index do |i|
|
|
85
|
+
vectors.push(@current[files[i]][cols[i].to_i])
|
|
86
|
+
end
|
|
87
|
+
x_formula, y_formula = set.split(':')
|
|
88
|
+
mods = @included_modules
|
|
89
|
+
return [Dvector.compute_formula(x_formula,vectors,mods),
|
|
90
|
+
Dvector.compute_formula(y_formula,vectors,mods)]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# source.rb : The implementation of a data source
|
|
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
|
+
module SciYAG
|
|
19
|
+
|
|
20
|
+
module Backends
|
|
21
|
+
|
|
22
|
+
# A data source is a class containing raw data, most probably under
|
|
23
|
+
# the form of a list of Dvectors. It is the job of Representations to
|
|
24
|
+
# transform that source into a 2D or 3D set.
|
|
25
|
+
class DataSource
|
|
26
|
+
|
|
27
|
+
# The list of the columns
|
|
28
|
+
attr_reader :columns
|
|
29
|
+
|
|
30
|
+
# A list of hashes of informations about the columns
|
|
31
|
+
attr_reader :columns_info
|
|
32
|
+
|
|
33
|
+
# Some informations about the source. Different possibilities:
|
|
34
|
+
# * :filename, the name of the file from where the source is
|
|
35
|
+
# coming;
|
|
36
|
+
# * :dataset, the name of dataset, if applicable.
|
|
37
|
+
# and so on...
|
|
38
|
+
attr_accessor :informations
|
|
39
|
+
|
|
40
|
+
# Creates a datasource, and fills it with the columns _columns_.
|
|
41
|
+
# It is better however to use directly #add_column to fill
|
|
42
|
+
# the source with Data.
|
|
43
|
+
def initialize(*columns)
|
|
44
|
+
@columns = []
|
|
45
|
+
@columns_info = []
|
|
46
|
+
@informations = {}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Automatic naming of the columns
|
|
50
|
+
def auto_name(number)
|
|
51
|
+
return "$#{number}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Add a column and its information to the list.
|
|
55
|
+
def add_column(col, name = nil, infos = {})
|
|
56
|
+
name = auto_name(col.length) unless name
|
|
57
|
+
@columns << col
|
|
58
|
+
infos[:name] = name
|
|
59
|
+
@columns_info << infos
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# text.rb : A simple backend to deal with basic text files.
|
|
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
|
+
|
|
19
|
+
|
|
20
|
+
require 'SciYAG/Backends/backend'
|
|
21
|
+
require 'Dobjects/Dvector'
|
|
22
|
+
require 'Dobjects/Function'
|
|
23
|
+
|
|
24
|
+
# For separated sets
|
|
25
|
+
require 'stringio'
|
|
26
|
+
|
|
27
|
+
module SciYAG
|
|
28
|
+
|
|
29
|
+
# A module for easy use of NaN in operations
|
|
30
|
+
module NaN
|
|
31
|
+
NaN = 0.0/0.0
|
|
32
|
+
def nan
|
|
33
|
+
return NaN
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
module Backends
|
|
38
|
+
|
|
39
|
+
class TextBackend < Backend
|
|
40
|
+
|
|
41
|
+
# A constant holding a relation extension -> command to
|
|
42
|
+
# decompress (to be fed to sprintf with the filename as argument)
|
|
43
|
+
UNCOMPRESSORS = {
|
|
44
|
+
".gz" => "gunzip -c %s",
|
|
45
|
+
".bz2" => "bunzip2 -c %s",
|
|
46
|
+
".lzma" => "unlzma -c %s",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
include Dobjects
|
|
50
|
+
|
|
51
|
+
describe 'text', 'Text format', <<EOD
|
|
52
|
+
This backend can read text files in a format close to the one understood
|
|
53
|
+
by gnuplot and the like.
|
|
54
|
+
EOD
|
|
55
|
+
|
|
56
|
+
# Inherit the baseline handling, can be useful !
|
|
57
|
+
inherit_parameters :base_line
|
|
58
|
+
|
|
59
|
+
param_accessor :skip, 'skip', "Skip lines", {:type => :integer},
|
|
60
|
+
"Number of lines to be skipped at the beginning of the file"
|
|
61
|
+
|
|
62
|
+
param_accessor :default_column_spec, 'col',
|
|
63
|
+
"Default column specification", {:type => :string},
|
|
64
|
+
"Which columns to use when the @1:2 syntax is not used"
|
|
65
|
+
|
|
66
|
+
param_accessor :split, 'split', "Split into subsets",
|
|
67
|
+
{:type => :boolean},
|
|
68
|
+
"If true, splits files into subsets on blank/non number lines"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
param_accessor :separator, 'separator', "Data columns separator",
|
|
72
|
+
{:type => :string_or_regexp},
|
|
73
|
+
"The columns separator. Defaults to /\s+/"
|
|
74
|
+
|
|
75
|
+
# param_accessor :select, 'select', "Select lines", {:type => :string},
|
|
76
|
+
# "Skips line where the code returns false"
|
|
77
|
+
|
|
78
|
+
def initialize
|
|
79
|
+
@dummy = nil
|
|
80
|
+
@current = nil
|
|
81
|
+
# Current is the name of the last file used. Necessary for '' specs.
|
|
82
|
+
@current_data = nil # The data of the last file used.
|
|
83
|
+
@skip = 0
|
|
84
|
+
@included_modules = [NaN] # to make sure we give them to
|
|
85
|
+
# Dvector.compute_formula
|
|
86
|
+
@default_column_spec = "1:2"
|
|
87
|
+
|
|
88
|
+
@separator = /\s+/
|
|
89
|
+
|
|
90
|
+
# We don't split data by default.
|
|
91
|
+
@split = false
|
|
92
|
+
|
|
93
|
+
super()
|
|
94
|
+
|
|
95
|
+
# Override Backend's cache - for now.
|
|
96
|
+
@cache = {} # A cache file_name -> data
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def extend(mod)
|
|
101
|
+
super
|
|
102
|
+
@included_modules << mod
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns a IO object suitable to acquire data from it for
|
|
106
|
+
# the given _file_, which can be one of the following:
|
|
107
|
+
# * a real file name
|
|
108
|
+
# * a compressed file name
|
|
109
|
+
# * a pipe command.
|
|
110
|
+
def get_io_object(file)
|
|
111
|
+
if file == "-"
|
|
112
|
+
return $stdin
|
|
113
|
+
elsif file =~ /(.*?)\|\s*$/ # A pipe
|
|
114
|
+
return IO.popen($1)
|
|
115
|
+
elsif not File.readable?(file)
|
|
116
|
+
# Try to find a compressed version
|
|
117
|
+
for ext,method in UNCOMPRESSORS
|
|
118
|
+
if File.readable? "#{file}#{ext}"
|
|
119
|
+
info "Using compressed file #{name}#{ext} in stead of #{name}"
|
|
120
|
+
return IO.popen(method % "#{file}#{ext}")
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
for ext, method in UNCOMPRESSORS
|
|
125
|
+
if file =~ /#{ext}$/
|
|
126
|
+
info "Taking file #{file} as a compressed file"
|
|
127
|
+
return IO.popen(method % file)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
return File::open(file)
|
|
131
|
+
end
|
|
132
|
+
error "Could not open #{file}"
|
|
133
|
+
return nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# A line is invalid if it is blank or starts
|
|
137
|
+
# neither with a digit nor +, - or .
|
|
138
|
+
#
|
|
139
|
+
# Maybe to be improved later.
|
|
140
|
+
InvalidLineRE = /^\s*$|^\s*[^\d+.\s-]+/
|
|
141
|
+
|
|
142
|
+
# Returns a string corresponding to the given _set_ of the
|
|
143
|
+
# given _io_ object.
|
|
144
|
+
#
|
|
145
|
+
# Sets are 1-based.
|
|
146
|
+
def get_set_string(io, set)
|
|
147
|
+
cur_set = 1
|
|
148
|
+
last_line_is_invalid = true
|
|
149
|
+
str = ""
|
|
150
|
+
line_number = 0
|
|
151
|
+
while line = io.gets
|
|
152
|
+
line_number += 1
|
|
153
|
+
if line =~ InvalidLineRE
|
|
154
|
+
debug "Found invalid line at #{line_number}"
|
|
155
|
+
if ! last_line_is_invalid
|
|
156
|
+
# We begin a new set.
|
|
157
|
+
cur_set += 1
|
|
158
|
+
debug "Found set #{cur_set} at line #{line_number}"
|
|
159
|
+
if(cur_set > set)
|
|
160
|
+
return str
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
last_line_is_invalid = true
|
|
164
|
+
else
|
|
165
|
+
last_line_is_invalid = false
|
|
166
|
+
if cur_set == set
|
|
167
|
+
str += line
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
return str
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Returns an IO object corresponding to the given file.
|
|
175
|
+
def get_io_set(file)
|
|
176
|
+
if not @split
|
|
177
|
+
return get_io_object(file)
|
|
178
|
+
else
|
|
179
|
+
file =~ /(.*?)(?:#(\d+))?$/; # ; to make ruby-mode indent correctly.
|
|
180
|
+
filename = $1
|
|
181
|
+
if $2
|
|
182
|
+
set = $2.to_i
|
|
183
|
+
else
|
|
184
|
+
set = 1
|
|
185
|
+
end
|
|
186
|
+
debug "Trying to get set #{set} from file '#{filename}'"
|
|
187
|
+
str = get_set_string(get_io_object(filename), set)
|
|
188
|
+
return StringIO.new(str)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Reads data from a file. If needed, extract the file from the columns
|
|
193
|
+
# specification.
|
|
194
|
+
def read_file(file)
|
|
195
|
+
if file =~ /(.*)@.*/
|
|
196
|
+
file = $1
|
|
197
|
+
end
|
|
198
|
+
name = file # As file will be modified.
|
|
199
|
+
if ! @cache.key?(file) # Read the file if it is not cached.
|
|
200
|
+
fancy_read_options = {'index_col' => true,
|
|
201
|
+
'skip_first' => @skip,
|
|
202
|
+
'sep' => @separator
|
|
203
|
+
}
|
|
204
|
+
io_set = get_io_set(file)
|
|
205
|
+
debug "Fancy read '#{file}', options #{fancy_read_options.inspect}"
|
|
206
|
+
@cache[name] = Dvector.fancy_read(io_set, nil, fancy_read_options)
|
|
207
|
+
end
|
|
208
|
+
return @cache[name]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# This is called by the architecture to get the data. It splits
|
|
213
|
+
# the set name into filename@cols, reads the file if necessary and
|
|
214
|
+
# calls get_data
|
|
215
|
+
def query_xy_data(set)
|
|
216
|
+
if set =~ /(.*)@(.*)/
|
|
217
|
+
col_spec = $2
|
|
218
|
+
file = $1
|
|
219
|
+
else
|
|
220
|
+
col_spec = @default_column_spec
|
|
221
|
+
file = set
|
|
222
|
+
end
|
|
223
|
+
if file.length > 0
|
|
224
|
+
@current_data = read_file(file)
|
|
225
|
+
@current = file
|
|
226
|
+
end
|
|
227
|
+
x,y,err = get_data(col_spec)
|
|
228
|
+
return [Function.new(x,y),err]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Reads the data using the columns specification, provided that
|
|
232
|
+
# the appropriate fle has already been loaded into @current. For now
|
|
233
|
+
# no single sanity check.
|
|
234
|
+
def get_data(col_spec)
|
|
235
|
+
# First, we must split the column specification into what
|
|
236
|
+
# I would call target specifications. A target is in the form
|
|
237
|
+
# of stuff=spec, where stuff can be basically anything. x=, y=,
|
|
238
|
+
# yea= are implied for the first specifications.
|
|
239
|
+
|
|
240
|
+
defaults = [:x,:y,:yea]
|
|
241
|
+
specifications = {} # A hash value spec => column spec
|
|
242
|
+
col_spec.split(/:/).each do |spec|
|
|
243
|
+
d = defaults.shift
|
|
244
|
+
if spec =~ /^\s*(\w+)\s*=(.*)/
|
|
245
|
+
spec = $2
|
|
246
|
+
d = $1.to_sym
|
|
247
|
+
end
|
|
248
|
+
specifications[d] = spec
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
debug "spec #{col_spec} becomes #{specifications.inspect}"
|
|
252
|
+
|
|
253
|
+
values = {}
|
|
254
|
+
if col_spec =~ /\$/ # There is a formula in the specification
|
|
255
|
+
for key,spec in specifications
|
|
256
|
+
formula = spec.gsub(/\$(\d+)/, 'column[\1]')
|
|
257
|
+
debug "Using formula '#{formula}' for #{key}"
|
|
258
|
+
values[key] = Dvector.
|
|
259
|
+
compute_formula(formula,
|
|
260
|
+
@current_data,
|
|
261
|
+
@included_modules)
|
|
262
|
+
end
|
|
263
|
+
else
|
|
264
|
+
for key,spec in specifications
|
|
265
|
+
values[key] = @current_data[spec.to_i].dup
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
errors = compute_error_bars(values)
|
|
269
|
+
# Now, we're left with a hash...
|
|
270
|
+
return [values[:x],values[:y], errors]
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# Turns a target => values specification into something usable as
|
|
274
|
+
# error bars, that is :xmin, :xmax and the like hashes. The rules
|
|
275
|
+
# are the following:
|
|
276
|
+
# * ?min/?max are passed on directly;
|
|
277
|
+
# * ?e(abs) are transformed into ?min = ? - ?eabs, ?max = ? + ?eabs
|
|
278
|
+
# * ?eu(p/?ed(own) are transformed respectively into ? +/- ?...
|
|
279
|
+
# * ?er(el) become ?min = ?*(1 - ?erel, ?max = ?(1 + ?erel)
|
|
280
|
+
# * ?erup/?erdown follow the same pattern...
|
|
281
|
+
def compute_error_bars(values)
|
|
282
|
+
target = {}
|
|
283
|
+
for key in values.keys
|
|
284
|
+
case key.to_s
|
|
285
|
+
when /^[xy](min|max)?$/
|
|
286
|
+
target[key] = values[key].dup # Just to make sure.
|
|
287
|
+
when /^(.)e(a(bs?)?)?$/
|
|
288
|
+
target["#{$1}min".to_sym] = values[$1.to_sym] - values[key]
|
|
289
|
+
target["#{$1}max".to_sym] = values[$1.to_sym] + values[key]
|
|
290
|
+
when /^(.)eu(p)?$/
|
|
291
|
+
target["#{$1}max".to_sym] = values[$1.to_sym] + values[key]
|
|
292
|
+
when /^(.)ed(o(wn?)?)?$/
|
|
293
|
+
target["#{$1}min".to_sym] = values[$1.to_sym] - values[key]
|
|
294
|
+
when /^(.)er(el?)?$/
|
|
295
|
+
target["#{$1}min".to_sym] = values[$1.to_sym] *
|
|
296
|
+
(values[key].neg + 1)
|
|
297
|
+
target["#{$1}max".to_sym] = values[$1.to_sym] *
|
|
298
|
+
(values[key] + 1)
|
|
299
|
+
when /^(.)erd(o(wn?)?)?$/
|
|
300
|
+
target["#{$1}min".to_sym] = values[$1.to_sym] *
|
|
301
|
+
(values[key].neg + 1)
|
|
302
|
+
when /^(.)erup?$/
|
|
303
|
+
target["#{$1}max".to_sym] = values[$1.to_sym] *
|
|
304
|
+
(values[key] + 1)
|
|
305
|
+
else
|
|
306
|
+
warn "Somehow, the target specification #{key} " +
|
|
307
|
+
"didn't make it through"
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
return target
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Expands specifications into few sets. This function will separate the
|
|
314
|
+
# set into a file spec and a col spec. Within the col spec, the 2##6
|
|
315
|
+
# keyword is used to expand to 2,3,4,5,6. 2## followed by a non-digit
|
|
316
|
+
# expands to 2,...,last column in the file. For now, the expansions
|
|
317
|
+
# stops on the first occurence found, and the second form doesn't
|
|
318
|
+
# work yet. But soon...
|
|
319
|
+
def expand_sets(spec)
|
|
320
|
+
if m = /(\d+)##(\D|$)/.match(spec)
|
|
321
|
+
a = m[1].to_i
|
|
322
|
+
trail = m[2]
|
|
323
|
+
b = read_file(spec)
|
|
324
|
+
b = (b.length - 1)
|
|
325
|
+
ret = []
|
|
326
|
+
a.upto(b) do |i|
|
|
327
|
+
ret << m.pre_match + i.to_s + trail + m.post_match
|
|
328
|
+
end
|
|
329
|
+
return ret
|
|
330
|
+
else
|
|
331
|
+
return super
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
end
|