ctioga 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/COPYING +340 -0
  2. data/ctioga/bin/ctable +28 -0
  3. data/ctioga/bin/ctioga +37 -0
  4. data/ctioga/doc/ctable.1 +156 -0
  5. data/ctioga/doc/ctioga.1 +2363 -0
  6. data/ctioga/examples/README +46 -0
  7. data/ctioga/examples/ctioga.gnuplot +4 -0
  8. data/ctioga/examples/ctioga_within_tioga.rb +53 -0
  9. data/ctioga/examples/ctiogarc.rb +24 -0
  10. data/ctioga/examples/include_1.rb +15 -0
  11. data/ctioga/examples/noise.dat +100 -0
  12. data/ctioga/examples/noise.rb +13 -0
  13. data/ctioga/examples/trig.csv +100 -0
  14. data/ctioga/examples/trig.dat +100 -0
  15. data/ctioga/examples/trig.rb +14 -0
  16. data/ctioga/examples/trigh.dat +100 -0
  17. data/ctioga/examples/trigh.rb +10 -0
  18. data/ctioga/examples/tutorial +763 -0
  19. data/ctioga/examples/tutorial.sh +269 -0
  20. data/ctioga/tests/README +14 -0
  21. data/ctioga/tests/axes.sh +40 -0
  22. data/ctioga/tests/basic.sh +11 -0
  23. data/ctioga/tests/draw.sh +24 -0
  24. data/ctioga/tests/histograms.sh +14 -0
  25. data/ctioga/tests/insets.sh +41 -0
  26. data/ctioga/tests/layouts.sh +29 -0
  27. data/ctioga/tests/legends.sh +113 -0
  28. data/ctioga/tests/styles.sh +43 -0
  29. data/ctioga/tests/test_style.sh +8 -0
  30. data/ctioga/tests/tests.sh +24 -0
  31. data/ctioga/tests/text_backend.sh +83 -0
  32. data/ctioga/tests/tioga_defaults.rb +18 -0
  33. data/lib/CTioga/axes.rb +904 -0
  34. data/lib/CTioga/backends.rb +88 -0
  35. data/lib/CTioga/boundaries.rb +224 -0
  36. data/lib/CTioga/ctable.rb +134 -0
  37. data/lib/CTioga/curve_style.rb +246 -0
  38. data/lib/CTioga/debug.rb +199 -0
  39. data/lib/CTioga/dimension.rb +133 -0
  40. data/lib/CTioga/elements.rb +17 -0
  41. data/lib/CTioga/elements/base.rb +84 -0
  42. data/lib/CTioga/elements/containers.rb +578 -0
  43. data/lib/CTioga/elements/curves.rb +368 -0
  44. data/lib/CTioga/elements/tioga_primitives.rb +440 -0
  45. data/lib/CTioga/layout.rb +595 -0
  46. data/lib/CTioga/legends.rb +29 -0
  47. data/lib/CTioga/legends/cmdline.rb +187 -0
  48. data/lib/CTioga/legends/item.rb +164 -0
  49. data/lib/CTioga/legends/style.rb +257 -0
  50. data/lib/CTioga/log.rb +73 -0
  51. data/lib/CTioga/movingarrays.rb +131 -0
  52. data/lib/CTioga/partition.rb +271 -0
  53. data/lib/CTioga/plot_style.rb +230 -0
  54. data/lib/CTioga/plotmaker.rb +1677 -0
  55. data/lib/CTioga/shortcuts.rb +69 -0
  56. data/lib/CTioga/structures.rb +82 -0
  57. data/lib/CTioga/styles.rb +140 -0
  58. data/lib/CTioga/themes.rb +581 -0
  59. data/lib/CTioga/themes/classical.rb +82 -0
  60. data/lib/CTioga/themes/demo.rb +63 -0
  61. data/lib/CTioga/themes/fits.rb +91 -0
  62. data/lib/CTioga/themes/mono.rb +33 -0
  63. data/lib/CTioga/tioga.rb +32 -0
  64. data/lib/CTioga/utils.rb +173 -0
  65. data/lib/MetaBuilder/Parameters/dates.rb +38 -0
  66. data/lib/MetaBuilder/Parameters/lists.rb +132 -0
  67. data/lib/MetaBuilder/Parameters/numbers.rb +69 -0
  68. data/lib/MetaBuilder/Parameters/strings.rb +86 -0
  69. data/lib/MetaBuilder/Parameters/styles.rb +75 -0
  70. data/lib/MetaBuilder/Qt4/Parameters/dates.rb +51 -0
  71. data/lib/MetaBuilder/Qt4/Parameters/numbers.rb +65 -0
  72. data/lib/MetaBuilder/Qt4/Parameters/strings.rb +106 -0
  73. data/lib/MetaBuilder/Qt4/parameter.rb +172 -0
  74. data/lib/MetaBuilder/Qt4/parameters.rb +9 -0
  75. data/lib/MetaBuilder/descriptions.rb +603 -0
  76. data/lib/MetaBuilder/factory.rb +101 -0
  77. data/lib/MetaBuilder/group.rb +57 -0
  78. data/lib/MetaBuilder/metabuilder.rb +10 -0
  79. data/lib/MetaBuilder/parameter.rb +374 -0
  80. data/lib/MetaBuilder/parameters.rb +11 -0
  81. data/lib/MetaBuilder/qt4.rb +8 -0
  82. data/lib/SciYAG/Backends/backend.rb +379 -0
  83. data/lib/SciYAG/Backends/binner.rb +168 -0
  84. data/lib/SciYAG/Backends/cache.rb +102 -0
  85. data/lib/SciYAG/Backends/dataset.rb +158 -0
  86. data/lib/SciYAG/Backends/descriptions.rb +469 -0
  87. data/lib/SciYAG/Backends/filters.rb +25 -0
  88. data/lib/SciYAG/Backends/filters/average.rb +134 -0
  89. data/lib/SciYAG/Backends/filters/cumulate.rb +37 -0
  90. data/lib/SciYAG/Backends/filters/filter.rb +70 -0
  91. data/lib/SciYAG/Backends/filters/norm.rb +39 -0
  92. data/lib/SciYAG/Backends/filters/smooth.rb +63 -0
  93. data/lib/SciYAG/Backends/filters/sort.rb +43 -0
  94. data/lib/SciYAG/Backends/filters/strip.rb +34 -0
  95. data/lib/SciYAG/Backends/filters/trim.rb +64 -0
  96. data/lib/SciYAG/Backends/gnuplot.rb +131 -0
  97. data/lib/SciYAG/Backends/math.rb +108 -0
  98. data/lib/SciYAG/Backends/mdb.rb +462 -0
  99. data/lib/SciYAG/Backends/multitext.rb +96 -0
  100. data/lib/SciYAG/Backends/source.rb +64 -0
  101. data/lib/SciYAG/Backends/text.rb +339 -0
  102. data/lib/SciYAG/backends.rb +16 -0
  103. metadata +191 -0
@@ -0,0 +1,11 @@
1
+ # parameters.rb: A file grouping all the require necessary to have a
2
+ # working parameter system.
3
+ # This file is copyright 2006 by Vincent Fourmond, but you can do whatever
4
+ # you want with it.
5
+
6
+ require 'MetaBuilder/parameter'
7
+ require 'MetaBuilder/Parameters/numbers'
8
+ require 'MetaBuilder/Parameters/strings'
9
+ require 'MetaBuilder/Parameters/lists'
10
+ require 'MetaBuilder/Parameters/styles'
11
+ require 'MetaBuilder/Parameters/dates'
@@ -0,0 +1,8 @@
1
+ # qt4.rb: Use this file to include Qt support for parameters in an
2
+ # application.
3
+
4
+ # This file is copyright 2006 by Vincent Fourmond, but you can do whatever
5
+ # you want with it.
6
+
7
+ require 'MetaBuilder/Qt4/parameters'
8
+
@@ -0,0 +1,379 @@
1
+ # backend.rb : The base of the arcitecture of the Backends
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
+ # Filters and descriptions
19
+ require 'MetaBuilder/metabuilder'
20
+ require 'SciYAG/Backends/descriptions'
21
+ require 'SciYAG/Backends/filters'
22
+ require 'SciYAG/Backends/dataset'
23
+ require 'SciYAG/Backends/cache'
24
+
25
+ # Document-class: SciYAG
26
+ # The SciYAG module contains all the classes related to Backend and Filter.
27
+ # It will also contain additionnal features in a not-so-distant future.
28
+ module SciYAG
29
+
30
+ module Backends
31
+
32
+ # A simple class to describe a backend. See the
33
+ # Descriptions::Description
34
+ class BackendDescription < MetaBuilder::Description
35
+ # The backend's banner.
36
+ def banner(instance)
37
+ "Backend '#{instance.long_name}'"
38
+ end
39
+
40
+ # Creates a new backend and optionnally registers it
41
+ def initialize(cls, name, long_name, desc, register = true)
42
+ super(cls, name, long_name, desc)
43
+ if register
44
+ Backend.register_class(self)
45
+ end
46
+ end
47
+ end
48
+
49
+
50
+ # This class provides the infrastructure for accessing data sets. It
51
+ # shouldn't be used directly, but rather subclassed and reimplemented.
52
+ # The aim of this class is to provide any software which is interested
53
+ # to retrive data from some source with a consistent way to do so,
54
+ # independent the kind of source accessed.
55
+ #
56
+ # Subclasses should:
57
+ # * provide a consistent method for creating themselves,
58
+ # with as much information as necessary, including options and default
59
+ # parameters. Actually, their initialize function should take no value
60
+ # bu on the other side, the BackendDescription associated with it
61
+ # should make it easy to set all the parameters necessary to
62
+ # get one set of data.
63
+ # * provide a way to fill an OptionParser with their own parameters
64
+ # * provide a way to retrieve the data via named 'sets' (either 2D or 3D
65
+ # data, depending on the subclass)
66
+ # * provide a way to obtain all meta-informations on one dataset,
67
+ # such as the date, the meaning of the columns (if any), and so on.
68
+ # * provide a way to know which named sets are available, or at least
69
+ # a subset (or nothing if we don't know a thing).
70
+ # * wether the actual reading of the data is done at initialization time
71
+ # or at query time is left to the implementor ;-) !
72
+
73
+ class Backend
74
+
75
+ # Import the main description functions into the appropriate
76
+ # namespaces
77
+ extend MetaBuilder::DescriptionExtend
78
+ include MetaBuilder::DescriptionInclude
79
+
80
+ # Backend is a factory, but no autoregistering is made.
81
+ create_factory false
82
+
83
+ # Sets up a few things, such as the filters.
84
+ def initialize()
85
+ @xy_filters = []
86
+ @xy_filters_apply = false
87
+
88
+ @xyz_filters = []
89
+ @xyz_filters_apply = false
90
+
91
+ # If set, uses this set as a baseline for all the others.
92
+ @base_line = ""
93
+ @base_line_cache = false
94
+
95
+ # Filters are classes that have one method apply, which takes a
96
+ # pair/triplet of vectors and return the same number of stuff,
97
+ # modified or not.
98
+
99
+
100
+ # We create a cache by default. Doesn't take up much space anyway:
101
+ @cache = Cache.new
102
+ end
103
+
104
+ def push_xy_filter(f)
105
+ @xy_filters << f
106
+ @xy_filters_apply = true
107
+ end
108
+
109
+ # Removes a filter from the top
110
+ def pop_xy_filter
111
+ return @xy_filters.pop
112
+ end
113
+
114
+ # Removes all filters on the list.
115
+ def clear_xy_filters
116
+ @xy_filters = []
117
+ @xy_filters_apply = false
118
+ end
119
+
120
+
121
+ # Creates a description object with the given texts and associates
122
+ # it with the class. It is necessary to have this statement
123
+ # *before* any parameter declaration. If you don't set any description,
124
+ # you will not be able to benefit from the plugin system.
125
+ # To be used in Backend subclasses, simply this way:
126
+ #
127
+ # describe "biniou", "Biniou backend", "A backend to deal with Binious"
128
+ #
129
+ def Backend.describe(name, longname, desc, register = true)
130
+ d = BackendDescription.new(self, name, longname, desc, register)
131
+ set_description(d)
132
+ end
133
+
134
+ # Returns a hash containing the description of all available backends
135
+ def Backend.list_backends
136
+ return factory_description_hash
137
+ end
138
+
139
+ def Backend.list_descriptions
140
+ warn "Backend.list_descriptions should not be used, use Backend.list_backends instead"
141
+ list_backends
142
+ end
143
+
144
+ describe 'backend', 'The base class for backends', <<EOD, false
145
+ This is the base class for backends. It should never be used directly.
146
+ EOD
147
+
148
+ # A hook to set a baseline:
149
+ param_reader :base_line=, :base_line, "baseline", "Base line",
150
+ {:type => :string, }, "Sets a baseline for subsequent data sets"
151
+
152
+
153
+ def base_line=(str)
154
+ if str =~ /^no$/ or str.empty?
155
+ @base_line = ""
156
+ else
157
+ @base_line = expand_sets(str)[0]
158
+ # Fill the cache.
159
+ ary = query_xy_data(@base_line)
160
+ @base_line_cache = if ary.is_a?(Array)
161
+ ary[0]
162
+ else
163
+ ary
164
+ end
165
+ end
166
+ end
167
+
168
+ # This function should return a hash containing all meta-information
169
+ # available about the given set. The hash can contain elements such as:
170
+ #
171
+ # <tt>:date</tt>:: the date at which the set was recorded
172
+ # <tt>:x_legend</tt>:: legend of the X axis
173
+ # <tt>:x_unit</tt>:: unit of the X axis
174
+ # (and the same kind for Y and Z axis)
175
+ #
176
+ # Of course, this list is not limitative; you are encouraged at any rate
177
+ # to add as much metadata as possible. Later on, I'll provide a method
178
+ # to register metadata types.
179
+
180
+ def meta_data(set)
181
+ warn "No metadata implementation for backend " +
182
+ "#{description.name}"
183
+ end
184
+
185
+ # Returns true if the backend can provide data for the given set.
186
+ def has_set?(set)
187
+ return false
188
+ end
189
+
190
+ alias set? has_set?
191
+
192
+ # Returns :xy or :xyz depending on the kind of the given set.
193
+ def set_type(set)
194
+ raise "Shouldn't be called for the base class"
195
+ end
196
+
197
+ # This function must be redefined by children who provide
198
+ # 2D datasets. This function must return either:
199
+ # * a Function alone, representing the 2D data of the set
200
+ # * or an Array, whose first element is a Function and whose
201
+ # second element is an array containing metadata about the
202
+ # dataset.
203
+ def query_xy_data(set)
204
+ raise "query_xy_data must be redefined by children !"
205
+ end
206
+
207
+ # Used by other classes to query for the Backends data. This may
208
+ # include processing with data filters. Please note that the
209
+ # query_xy_data functions *must* return a Dobjects::Function.
210
+ # The return value *must* be modifiable without consequences to
211
+ # the backend.
212
+ def xy_data(set)
213
+ retval = query_xy_data(set)
214
+ if retval.is_a?(Array)
215
+ ary,errors,meta = *retval
216
+ else
217
+ ary = retval
218
+ errors = {}
219
+ meta = {}
220
+ end
221
+ if (not @base_line.empty?) and @base_line_cache
222
+ ary.y.sub!(@base_line_cache.y)
223
+ end
224
+ # Now, this is the fun part: we create the Dataset object
225
+ dataset = DataSet2D.new(self, ary, errors, meta)
226
+ # apply the filters if necessary
227
+ if @xy_filters_apply
228
+ for filter in @xy_filters
229
+ filter.apply!(dataset)
230
+ end
231
+ end
232
+ return dataset
233
+ end
234
+
235
+ # Returns the XYZ data for the given set
236
+ def xyz_data(set)
237
+ ary = query_xyz_data(set)
238
+ # apply the filters if necessary
239
+ if @xyz_filters_apply
240
+ for filter in @xyz_filters
241
+ ary = filter.apply(ary)
242
+ end
243
+ end
244
+ return ary
245
+ end
246
+
247
+
248
+ # When converting a user input into a set, a program should
249
+ # *always* use this function, unless it has really good reasons for
250
+ # that.
251
+ #
252
+ # The default implementation is to expand 2##4 to 2, 3, 4. Can be
253
+ # useful even for mathematical stuff.
254
+ #
255
+ # Another thing is recognised and expanded:
256
+ # #<2<i*2>,5> runs the code i*2 with the values from 2 to 5 and
257
+ # returns the result. The code in the middle is a Ruby block, and therefore
258
+ # should be valid !
259
+ #
260
+ # A third expansion is now available:
261
+ # #<a = 2<a * sin(x)>10> will expand into 2*sin(x) , 3*sin(x) ... 10*sin(x)
262
+ # it is different than the previous in the sense that the code in the
263
+ # middle is not a Ruby code, but a mere string, which means there won't be
264
+ # compilation problems.
265
+ #
266
+ # Unless your backend can't accomodate for that, all redefinitions
267
+ # of this function should check for their specific signatures
268
+ # first and call this function if they fail. This way, they
269
+ # will profit from improvements in this code while keeping
270
+ # old stuff working.
271
+ def expand_sets(spec)
272
+ if m = /(\d+)##(\d+)/.match(spec)
273
+ debug "Using expansion rule #1"
274
+ a = m[1].to_i
275
+ b = m[2].to_i
276
+ ret = []
277
+ a.upto(b) do |i|
278
+ ret << m.pre_match + i.to_s + m.post_match
279
+ end
280
+ return ret
281
+ elsif m = /\#<(\d+)<(.*?)>(\d+)>/.match(spec)
282
+ debug "Using expansion rule #2"
283
+ from = m[1].to_i
284
+ to = m[3].to_i
285
+ debug "Ruby code used for expansion: {|i| #{m[2]} }"
286
+ code = eval "proc {|i| #{m[2]} }"
287
+ ret = []
288
+ from.upto(to) do |i|
289
+ ret << m.pre_match + code.call(i).to_s + m.post_match
290
+ end
291
+ return ret
292
+ elsif m = /\#<\s*(\w+)\s*=\s*(\d+)\s*<(.*?)>\s*(\d+)\s*>/.match(spec)
293
+ debug "Using expansion rule #3"
294
+ var = m[1]
295
+ from = m[2].to_i
296
+ to = m[4].to_i
297
+ # Then we replace all occurences of the variable
298
+ literal = '"' + m[3].gsub(/\b#{var}\b/, '#{' + var + '}') + '"'
299
+ debug "Ruby code used for expansion: {|#{var}| #{literal} }"
300
+ code = eval "proc {|#{var}| #{literal} }"
301
+ ret = []
302
+ from.upto(to) do |i|
303
+ ret << m.pre_match + code.call(i).to_s + m.post_match
304
+ end
305
+ return ret
306
+ end
307
+ # Fallback
308
+ return [spec]
309
+ rescue Exception => ex
310
+ # In case something went wrong in the eval.
311
+ warn "An error occured during expansion of '#{spec}': #{ex.message}"
312
+ debug "Error backtrace: #{ex.backtrace.join "\n"}"
313
+ warn "Ignoring, but you're nearly garanteed something will "+
314
+ "fail later on"
315
+ return [spec]
316
+ end
317
+
318
+ # Some backends have a pretty good idea of the sets available for use.
319
+ # Some really don't. You can choose to reimplement this function if
320
+ # you can provide a useful list of sets for your backend. This list
321
+ # doesn't need to be exhaustive (and is most unlikely to be). It can
322
+ # also return something that would need further expansion using
323
+ # expand_sets.
324
+ def sets_available
325
+ return []
326
+ end
327
+
328
+ # Gets a cached entry or generate it and cache it. See Cache#cache
329
+ # for more details. The cache's meta_data is constructed as following:
330
+ # * the current state of the backend is taken
331
+ # * keys inside _exclude_ are removed.
332
+ # * _supp_info_ is added
333
+ def get_cached_entry(name, exclude = [], supp_info = {}, &code)
334
+ state = save_state
335
+ for k in exclude
336
+ state.delete(k)
337
+ end
338
+ state.merge!(supp_info)
339
+ return @cache.get_cache(name, state, &code)
340
+ end
341
+
342
+ # Returns the default state of the named backend,
343
+ # or nil if it wasn't found.
344
+ def self.default_state(name)
345
+ desc = factory_description_hash[name]
346
+ if desc
347
+ return desc.default_state
348
+ else
349
+ return nil
350
+ end
351
+ end
352
+
353
+ @@log = nil
354
+
355
+ # Set the logger for Backends
356
+ def self.logger= (logger)
357
+ @@log = logger
358
+ end
359
+
360
+ # Facilities for logging: we forward all functions that look
361
+ # like logging facility to the @@log class variable, if that
362
+ # one responds to it.
363
+ methods = %w(warn info debug error fatal)
364
+ for meth in methods
365
+ eval <<"EOE"
366
+ def #{meth}(*args)
367
+ if @@log.respond_to? :#{meth}
368
+ @@log.#{meth}(*args)
369
+ end
370
+ end
371
+ EOE
372
+ end
373
+
374
+ # ruby.el really isn't happy with this one
375
+ private *methods.map {|t| t.to_sym}
376
+
377
+ end
378
+ end
379
+ end
@@ -0,0 +1,168 @@
1
+ # binner.rb : a binning backend to make histograms
2
+ # Copyright (C) 2008 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
+ module SciYAG
25
+
26
+ module Backends
27
+
28
+ class BinnerBackend < Backend
29
+
30
+ include Dobjects
31
+
32
+ describe 'binner', 'Automatic binner', <<EOD
33
+ Reads 1D data and bins them, giving the average position of the
34
+ bin and counts.
35
+ EOD
36
+
37
+
38
+ param_accessor :number, 'number', "Number of bins", :integer,
39
+ "Number of bins"
40
+
41
+ param_accessor :x_range, 'xrange', "X Range", :float_range,
42
+ "X range (a:b)"
43
+
44
+ param_accessor :normalize, 'norm', "Normalize", :boolean,
45
+ "Whether to divide by the total"
46
+
47
+ param_accessor :bin_size, 'bin', "Step size", :float,
48
+ "The bin size"
49
+
50
+
51
+ def initialize
52
+ @number = 20
53
+ @skip = 0
54
+ @separator = /\s+/
55
+ @default_column_spec = "1"
56
+
57
+ @x_range = false
58
+ @normalize = false
59
+
60
+ @bin_size = false
61
+
62
+ super()
63
+
64
+ @cache = {}
65
+ end
66
+
67
+
68
+ # Reads data from a file. If needed, extract the file from the set
69
+ # specification.
70
+ def read_file(file)
71
+ if file =~ /(.*)@.*/
72
+ file = $1
73
+ end
74
+ name = file # As file will be modified.
75
+ if ! @cache.key?(file) # Read the file if it is not cached.
76
+ if file == "-"
77
+ file = $stdin
78
+ elsif file =~ /(.*?)\|\s*$/
79
+ file = IO.popen($1)
80
+ end
81
+ fancy_read_options = {'index_col' => true,
82
+ 'skip_first' => @skip,
83
+ 'sep' => @separator
84
+ }
85
+ debug "Fancy read '#{file}', options #{fancy_read_options.inspect}"
86
+ @cache[name] = Dvector.fancy_read(file, nil, fancy_read_options)
87
+ end
88
+ return @cache[name]
89
+ end
90
+
91
+
92
+ # This is called by the architecture to get the data. It splits
93
+ # the set name into filename@cols, reads the file if necessary and
94
+ # calls get_data
95
+ def query_xy_data(set)
96
+ if set =~ /(.*)@(.*)/
97
+ col_spec = $2
98
+ file = $1
99
+ else
100
+ col_spec = @default_column_spec
101
+ file = set
102
+ end
103
+ if file.length > 0
104
+ @current_data = read_file(file)
105
+ @current = file
106
+ end
107
+ x,y = get_data(col_spec)
108
+ return Function.new(x,y)
109
+ end
110
+
111
+ # Reads the data using the columns specification, provided that
112
+ # the appropriate fle has already been loaded into @current. For now
113
+ # no single sanity check.
114
+ def get_data(col_spec)
115
+ if col_spec =~ /\$/ # There is a formula in the specification
116
+ formula = col_spec.gsub(/\$(\d+)/, 'column[\1]')
117
+ debug "Using formula '#{formula}'"
118
+ data = Dvector.
119
+ compute_formula(formula,
120
+ @current_data,[])
121
+ else
122
+ data = @current_data[col_spec.to_i].dup
123
+ end
124
+
125
+ # Now, data is a single Dvector of numbers. We want to bin it:
126
+ if @x_range
127
+ min = @x_range.first
128
+ max = @x_range.last
129
+ else
130
+ min = data.min
131
+ max = data.max
132
+ end
133
+
134
+
135
+ if @bin_size
136
+ delta = @bin_size
137
+ nb_bins = (((max - min).abs)/@bin_size).ceil.to_i + 1
138
+ else
139
+ nb_bins = @number
140
+ delta = (max - min)/(nb_bins - 1)
141
+ end
142
+
143
+ # We create a X Dvector:
144
+ x_values = Dvector.new(nb_bins)
145
+ y_values = Dvector.new(nb_bins)
146
+ nb_bins.times do |i|
147
+ x_values[i] = min + delta * i
148
+ y_values[i] = 0
149
+ end
150
+
151
+ # Now, we bin it:
152
+ for val in data
153
+ i = ((val - min)/delta).round
154
+ y_values[i] += 1
155
+ end
156
+
157
+ if @normalize
158
+ y_values /= data.size
159
+ end
160
+
161
+ return [x_values, y_values]
162
+ end
163
+
164
+ end
165
+
166
+ end
167
+
168
+ end