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,73 @@
1
+ # log.rb, copyright (c) 2006 by Vincent Fourmond:
2
+ # The general logging functions for Ctioga
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 'logger'
15
+ require 'forwardable'
16
+
17
+ module CTioga
18
+
19
+ Version::register_svn_info('$Revision: 653 $', '$Date: 2007-11-15 21:58:42 +0100 (Thu, 15 Nov 2007) $')
20
+
21
+ # This module contains code to be included by PlotMaker for debugging.
22
+ # Even if it doesn't deserve a real module of it's own, it makes sense
23
+ # to have it separated anyway.
24
+ module Log
25
+
26
+ extend Forwardable
27
+ def_delegators :@@log, :debug, :warn, :info, :error, :fatal
28
+
29
+ def init_logger(stream = STDERR)
30
+ Logger::Formatter::Format.replace("[%4$s] %6$s\n")
31
+ @@log = Logger.new(stream)
32
+ @@log.level = Logger::WARN # Warnings and more only by default
33
+ end
34
+
35
+ # Simple accessor for the @@log class variable.
36
+ def logger
37
+ return @@log
38
+ end
39
+
40
+ def logger_options(opt)
41
+ opt.on("-v", "--verbose", "Display useful information") do
42
+ @@log.level = Logger::INFO
43
+ end
44
+ opt.on("--debug", "Turn on debugging info") do
45
+ @@log.level = Logger::DEBUG
46
+ end
47
+ opt.on("--quiet", "Display only errors") do
48
+ @@log.level = Logger::ERROR
49
+ end
50
+ end
51
+
52
+ # A logging replacement for system
53
+ def spawn(cmd, priority = :info)
54
+ retval = system(cmd)
55
+ self.send(priority, "Running #{cmd} -> " +
56
+ if retval
57
+ "success"
58
+ else
59
+ "failure"
60
+ end
61
+ )
62
+ return retval
63
+ end
64
+
65
+ # Returns a string suitable for identification of an object, but
66
+ # without instance variables.
67
+ def identify(obj)
68
+ return "#<#{obj.class} 0x%x>" % obj.object_id
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,131 @@
1
+ # movingarray.rb, copyright (c) 2007 by Vincent Fourmond:
2
+ # Moving arrays
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 'Tioga/FigureConstants'
16
+
17
+
18
+ module CTioga
19
+
20
+ Version::register_svn_info('$Revision: 854 $', '$Date: 2008-11-27 23:21:51 +0100 (Thu, 27 Nov 2008) $')
21
+
22
+ # A helper function that converts user input into a Tioga
23
+ # color.
24
+ #
25
+ # TODO: allow designs such as in LaTeX xcolor: Red!10!Blue !
26
+ def self.get_tioga_color(str)
27
+ if str =~ /([\d.]+),([\d.]+),([\d.]+)/ # Array notation
28
+ color = Dobjects::Dvector.new([$1.to_f,$2.to_f,$3.to_f])
29
+ if color.max > 1
30
+ color *= 1.0/255.0
31
+ end
32
+ return color.to_a
33
+ elsif str =~ /#([0-9a-fA-F]{6})/ # HTML notation
34
+ return $1.scan(/../).map { |i| i.to_i(16)/255.0 }
35
+ else
36
+ return Tioga::FigureConstants.const_get(str)
37
+ end
38
+ end
39
+
40
+ # This class is just a means to make an instance of Array stand out
41
+ class SpecialArray < Array
42
+ end
43
+
44
+
45
+ # The MovingArray class provides a way to scroll through an array,
46
+ # such as a set of colors, markers, linstyles, and so on. The class
47
+ # provides a way to set the value directly as well, and to forget it.
48
+ class MovingArray
49
+ include Tioga
50
+
51
+ def initialize(sets, current = nil, startpoint = 0)
52
+ @sets = sets
53
+
54
+ # Pick the first key as a default
55
+ current = @sets.keys.first unless current
56
+ choose_current_set(current)
57
+
58
+ @current_point = startpoint # the current point in the current set
59
+ end
60
+
61
+ def value
62
+ @current_point += 1
63
+ if @current_point >= @current_set.length
64
+ @current_point %= @current_set.length
65
+ end
66
+ return @current_set[@current_point - 1]
67
+ end
68
+
69
+ # Chooses the current set. If the name refers to an existing set,
70
+ # this one is chosen. If not, and if the name looks like a gradient
71
+ # specification, we interpret it as such. In any other case,
72
+ # the chosen set is the set containing only the argument. This way,
73
+ # to get a set containing a single color, you can use
74
+ #
75
+ # choose_current_set(Pink)
76
+ def choose_current_set(name)
77
+ @current_set_name = name
78
+ if @sets.key?(name)
79
+ @current_set_name = name
80
+ @current_set = @sets[name]
81
+ elsif name =~ /gradient:(.+)--(.+),(\d+)/
82
+ # Special case for color gradients
83
+ s = CTioga.get_tioga_color($1)
84
+ e = CTioga.get_tioga_color($2)
85
+ nb = $3.to_i
86
+ fact = if nb > 1
87
+ 1.0/(nb - 1) # The famous off-by one...
88
+ else
89
+ warn "Incorrect gradient number: #{nb}"
90
+ 1.0
91
+ end
92
+ array = []
93
+ nb.times do |i|
94
+ a = []
95
+ f = i * fact
96
+ e.each_index do |c|
97
+ a << s[c] * (1 - f) + e[c] * f
98
+ end
99
+ array << a
100
+ end
101
+ @current_set = array
102
+ else
103
+ if name.is_a? SpecialArray
104
+ @current_set = name
105
+ else
106
+ @current_set = [name]
107
+ end
108
+ end
109
+ end
110
+
111
+ # Returns the available sets.
112
+ def available_sets
113
+ return @sets.keys
114
+ end
115
+
116
+ # Tells whether the given name is a valid set. Takes care of the special
117
+ # case of gradients.
118
+ #
119
+ # TODO: this looks hackish, somehow, but I don't see a way to make
120
+ # that less so...
121
+ def valid_set?(name)
122
+ if name =~ /^gradient:/
123
+ return true
124
+ else
125
+ return @sets.key? name
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ end
@@ -0,0 +1,271 @@
1
+ # partition.rb: segment partitioning functions
2
+ # Copyright (c) 2008 by Vincent Fourmond
3
+
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 (in the COPYING file).
14
+
15
+ require 'CTioga/utils'
16
+
17
+
18
+ module CTioga
19
+
20
+ Version::register_svn_info('$Revision: 792 $', '$Date: 2008-05-23 00:19:31 +0200 (Fri, 23 May 2008) $')
21
+
22
+ # A module for small convenience functions.
23
+ module Utils
24
+
25
+ # The following code is stolen from SciYAG/lib/utils.rb,
26
+ # and is used to partition segments in natural-looking
27
+ # subdivisions.
28
+
29
+
30
+ # Our natural way to split decades
31
+ NaturalDistances = Dobjects::Dvector[1, 2, 2.5, 5, 10]
32
+
33
+ # Attempts to partition the given segment in at most _nb_
34
+ # segments of equal size. The segments don't necessarily start on
35
+ # the edge of the original segment
36
+ def self.partition_segment(min, max, nb)
37
+ if min > max
38
+ return partition_segment(max, min, nb)
39
+ elsif min.nan? or max.nan?
40
+ return [0] * nb
41
+ elsif min == max
42
+ return self.partition_segment(min * 0.7, min * 1.3, nb)
43
+ end
44
+ distance = max - min
45
+ min_distance = distance/(nb + 1.0) # Why + 1.0 ? To account
46
+ # for the space that could be left on the side.
47
+
48
+ # The order of magnitude of the distance:
49
+ order = min_distance.log10.floor
50
+
51
+ # A distance which is within [1, 10 [ (but the latter is never reached.
52
+ normalized_distance = min_distance * 10**(-order)
53
+ final_distance = NaturalDistances.min_gt(normalized_distance) *
54
+ 10**(order)
55
+ # puts "Distance: #{distance} in #{nb} : #{normalized_distance} #{final_distance}"
56
+
57
+ # We're getting closer now: we found the natural distance between
58
+ # ticks.
59
+
60
+ start = (min/final_distance).ceil * final_distance
61
+ retval = []
62
+ val = start
63
+ while val <= max
64
+ retval << val
65
+ # I use this to avoid potential cumulative addition
66
+ # rounding errors
67
+ val = start + final_distance * retval.size
68
+ end
69
+ return retval
70
+
71
+ end
72
+
73
+ # Our natural way to split decades - except that all successive
74
+ # element now divide each other.
75
+ NaturalDistancesNonLinear = Dobjects::Dvector[1, 2.5, 5, 10]
76
+
77
+ # A class that handles a "natural distance". Create it by giving
78
+ # the initial distance. You can then get its value, lower it,
79
+ # increase it, find the first/last element of an interval that is
80
+ # a multiple if it
81
+ class NaturalDistance
82
+
83
+ # Creates the biggest 'natural distance' that is smaller
84
+ # than _distance_
85
+ def initialize(distance)
86
+ @order = distance.log10.floor
87
+ normalized = distance * 10**(-@order)
88
+ @index = 0
89
+ for dist in NaturalDistances
90
+ if dist > normalized
91
+ break
92
+ else
93
+ @index += 1
94
+ end
95
+ end
96
+ end
97
+
98
+ # Returns the actual value of the distance
99
+ def value
100
+ return NaturalDistances[@index] * 10**(@order)
101
+ end
102
+
103
+ # Goes to the natural distance immediately under the current one
104
+ def decrease
105
+ if @index > 0
106
+ @index -= 1
107
+ else
108
+ @index = NaturalDistances.size - 1
109
+ @order -= 1
110
+ end
111
+ end
112
+
113
+ # Goes to the natural distance immediately under the current one
114
+ def increase
115
+ if @index < NaturalDistances.size - 1
116
+ @index += 1
117
+ else
118
+ @index = 0
119
+ @order += 1
120
+ end
121
+ end
122
+
123
+ # Find the minimum element inside the given interval
124
+ # that is a multiple of this distance
125
+ def find_minimum(x1, x2)
126
+ x1,x2 = x2, x1 if x1 > x2
127
+
128
+ dist = value
129
+ v = (x1/dist).ceil * dist
130
+ if v <= x2
131
+ return v
132
+ else
133
+ return false
134
+ end
135
+ end
136
+
137
+ # Returns the value of the next decade (ascending)
138
+ def next_decade(x)
139
+ decade = 10.**(@order + 1)
140
+ if @index == 0 # We stop at 0.5 if the increase is 0.5
141
+ decade *= 0.5
142
+ end
143
+ nb = Float((x/decade).ceil)
144
+ if nb == x/decade
145
+ return (nb + 1)*decade
146
+ else
147
+ return nb * decade
148
+ end
149
+ end
150
+
151
+ # Returns the number of elements to #next_decade
152
+ def nb_to_next_decade(x)
153
+ dist = value
154
+ dec = next_decade(x)
155
+ return dec/dist - (x/dist).ceil + 1
156
+ end
157
+
158
+ # Returns a list of all the values corresponding to
159
+ # the distance
160
+ def to_next_decade(x)
161
+ next_decade = next_decade(x)
162
+ dist = value
163
+ start = (x/dist).ceil * dist
164
+ retval = []
165
+ while start + retval.size * dist <= next_decade
166
+ retval << start + retval.size * dist
167
+ end
168
+ return retval
169
+ end
170
+
171
+ end
172
+
173
+
174
+ # Attempts to partition the segment image of _min_, _max_
175
+ # by the Proc object _to_ into at most _nb_ elements. The
176
+ # reverse of the transformation, _from_, has to be provided.
177
+ def self.partition_nonlinear(to, from, x1, x2, nb)
178
+ x1, x2 = x2, x1 if x1 > x2
179
+ if x1.nan? or x2.nan?
180
+ return [0] * nb
181
+ elsif x1 == x2 # Nothing to do
182
+ return self.partition_segment(x1 * 0.7, x2 * 1.3, nb)
183
+ end
184
+
185
+ xdist = x2 - x1
186
+ xdist_min = xdist/(nb + 1.0) # Why + 1.0 ? To account
187
+ # for the space that could be left on the side.
188
+
189
+ y1 = to.call(x1)
190
+ y2 = to.call(x2)
191
+
192
+ # Make sure y1 < y2
193
+ y1, y2 = y2, y1 if y1 > y2
194
+
195
+ # We first need to check if the linear partitioning of
196
+ # the target segment could be enough:
197
+
198
+ candidate = self.partition_segment(y1, y2, nb)
199
+ candidate_real = candidate.map(&from)
200
+
201
+ # We inspect the segment: if one of the length deviates from the
202
+ # average expected by more than 25%, we drop it
203
+
204
+ length = []
205
+ p candidate_real, xdist_min
206
+ 0.upto(candidate.size - 2) do |i|
207
+ length << (candidate_real[i+1] - candidate_real[i]).abs/(xdist_min)
208
+ end
209
+ p length
210
+ # If everything stays within 25% off, we keep that
211
+ if length.min > 0.75 and length.max < 1.7
212
+ return candidate
213
+ end
214
+
215
+
216
+ # We start with a geometric measure of the distance, that
217
+ # will most likely scale better:
218
+ ydist = y1 * (y2/y1).abs ** (1/(nb + 1.0))
219
+
220
+ cur_dist = NaturalDistance.new(ydist)
221
+
222
+ retval = []
223
+
224
+ cur_y = y1
225
+ # This flag is necessary to avoid infinite loops
226
+ last_was_decrease = false
227
+
228
+ distance_unchanged = 0
229
+ last_real_distance = false
230
+ while cur_y < y2
231
+ candidates = cur_dist.to_next_decade(cur_y)
232
+ # We now evaluate the distance in real
233
+ real_distance = (from.call(cur_y) - from.call(candidates.last)).abs/
234
+ candidates.size
235
+ if last_real_distance && (real_distance == last_real_distance)
236
+ distance_unchanged += 1
237
+ else
238
+ distance_unchanged = 0
239
+ end
240
+ # p [:cur_y=, cur_y, :y2=, y2, :real_distance, real_distance,
241
+ # :distance=, cur_dist, :xdist_min, xdist_min,
242
+ # :candidates=, *candidates]
243
+
244
+ if (real_distance > 1.25 * xdist_min) &&
245
+ (distance_unchanged < 3)
246
+ cur_dist.decrease
247
+ last_was_decrease = true
248
+ elsif real_distance < 0.75 * xdist_min &&
249
+ !last_was_decrease && (distance_unchanged < 3) &&
250
+ candidates.last <= 10 * y2
251
+ cur_dist.increase
252
+ last_was_decrease = false
253
+ else
254
+ retval += candidates
255
+ cur_y = candidates.last
256
+ last_was_decrease = false
257
+ end
258
+ last_real_distance = real_distance
259
+ end
260
+
261
+ # We need to select them so
262
+ return retval.select do |y|
263
+ y >= y1 and y <= y2
264
+ end
265
+
266
+ end
267
+
268
+
269
+ end
270
+
271
+ end