statsample 0.6.2 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +1 -1
- data/README.txt +40 -36
- data/demo/correlation_matrix.rb +11 -0
- data/demo/dominance_analysis_bootstrap.rb +0 -4
- data/demo/polychoric.rb +14 -6
- data/lib/distribution.rb +1 -0
- data/lib/distribution/normal.rb +18 -18
- data/lib/distribution/normalbivariate.rb +189 -11
- data/lib/statsample.rb +1 -1
- data/lib/statsample/bivariate/polychoric.rb +232 -129
- data/lib/statsample/bivariate/tetrachoric.rb +8 -4
- data/lib/statsample/combination.rb +2 -2
- data/lib/statsample/dominanceanalysis/bootstrap.rb +11 -6
- data/lib/statsample/factor/pca.rb +1 -1
- data/lib/statsample/graph/gdchart.rb +2 -2
- data/lib/statsample/graph/svgboxplot.rb +100 -100
- data/lib/statsample/graph/svggraph.rb +1 -1
- data/lib/statsample/graph/svghistogram.rb +1 -1
- data/lib/statsample/graph/svgscatterplot.rb +96 -98
- data/test/test_bivariate.rb +27 -4
- data/test/test_distribution.rb +17 -16
- metadata +5 -5
- data/lib/statsample/htmlreport.rb +0 -255
@@ -107,13 +107,14 @@ module Statsample
|
|
107
107
|
def threshold_y
|
108
108
|
@zac
|
109
109
|
end
|
110
|
+
# Summary of the analysis
|
110
111
|
def summary
|
111
112
|
rp=ReportBuilder.new()
|
112
113
|
rp.add(self)
|
113
114
|
rp.to_text
|
114
115
|
end
|
115
116
|
|
116
|
-
def to_reportbuilder(generator)
|
117
|
+
def to_reportbuilder(generator) # :nodoc:
|
117
118
|
section=ReportBuilder::Section.new(:name=>@name)
|
118
119
|
t=ReportBuilder::Table.new(:name=>_("Contingence Table"),:header=>["","Y=0","Y=1", "T"])
|
119
120
|
t.add_row(["X=0", @a,@b,@a+@b])
|
@@ -129,6 +130,7 @@ module Statsample
|
|
129
130
|
generator.parse_element(section)
|
130
131
|
end
|
131
132
|
|
133
|
+
# Creates a new tetrachoric object for analysis
|
132
134
|
def initialize(a,b,c,d)
|
133
135
|
@a,@b,@c,@d=a,b,c,d
|
134
136
|
@name=_("Tetrachoric correlation")
|
@@ -138,7 +140,9 @@ module Statsample
|
|
138
140
|
raise "All frequencies should be positive" if (@a < 0 or @b < 0 or @c < 0 or @d < 0)
|
139
141
|
compute
|
140
142
|
end
|
141
|
-
|
143
|
+
# Compute the tetrachoric correlation.
|
144
|
+
# Called on object creation.
|
145
|
+
#
|
142
146
|
def compute
|
143
147
|
|
144
148
|
#
|
@@ -412,7 +416,7 @@ module Statsample
|
|
412
416
|
end
|
413
417
|
|
414
418
|
|
415
|
-
def calculate_sdr
|
419
|
+
def calculate_sdr # :nodoc:
|
416
420
|
#
|
417
421
|
# COMPUTE SDR
|
418
422
|
#
|
@@ -442,7 +446,7 @@ module Statsample
|
|
442
446
|
@sdzero = Math::sqrt(((@aa + @bb) * (@aa + @cc) * (@bb + @dd) * (@cc + @dd)).quo(@tot)).quo(@tot ** 2 * @ss)
|
443
447
|
@sdr = @sdzero if (@r == 0)
|
444
448
|
end
|
445
|
-
private :calculate_cosine, :calculate_sdr, :compute, :gaussian_quadrature
|
449
|
+
private :calculate_cosine, :calculate_sdr, :compute_sdzero, :compute, :gaussian_quadrature
|
446
450
|
end
|
447
451
|
end
|
448
452
|
end
|
@@ -40,7 +40,7 @@ module Statsample
|
|
40
40
|
def next_value
|
41
41
|
@d.next_value
|
42
42
|
end
|
43
|
-
class CombinationRuby
|
43
|
+
class CombinationRuby # :nodoc:
|
44
44
|
attr_reader :data
|
45
45
|
def initialize(k,n)
|
46
46
|
raise "k<=n" if k>n
|
@@ -83,7 +83,7 @@ module Statsample
|
|
83
83
|
end
|
84
84
|
|
85
85
|
# rb-gsl engine for Combinations
|
86
|
-
class CombinationGsl
|
86
|
+
class CombinationGsl # :nodoc:
|
87
87
|
def initialize(k,n)
|
88
88
|
require 'gsl'
|
89
89
|
raise "k<=n" if k>n
|
@@ -23,13 +23,16 @@ module Statsample
|
|
23
23
|
attr_accessor :ds
|
24
24
|
# Name of analysis
|
25
25
|
attr_accessor :name
|
26
|
-
# Alpha level of confidence
|
26
|
+
# Alpha level of confidence. Default: ALPHA
|
27
27
|
attr_accessor :alpha
|
28
|
+
# Debug?
|
29
|
+
attr_accessor :debug
|
28
30
|
# Create a new Dominance Analysis Bootstrap Object
|
29
31
|
#
|
30
32
|
# * ds: A Dataset object
|
31
33
|
# * y_var: Name of dependent variable
|
32
34
|
# * opts: Any other attribute of the class
|
35
|
+
ALPHA=0.95
|
33
36
|
def initialize(ds,y_var, opts=Hash.new)
|
34
37
|
@ds=ds
|
35
38
|
@y_var=y_var
|
@@ -37,7 +40,8 @@ module Statsample
|
|
37
40
|
@fields=ds.fields-[y_var]
|
38
41
|
@samples_ga=@fields.inject({}){|a,v| a[v]=[];a}
|
39
42
|
@n_samples=0
|
40
|
-
@alpha=
|
43
|
+
@alpha=ALPHA
|
44
|
+
@debug=false
|
41
45
|
@regression_class=Regression::Multiple::RubyEngine
|
42
46
|
@name=_("Bootstrap dominance Analysis: %s over %s") % [ ds.fields.join(",") , @y_var]
|
43
47
|
opts.each{|k,v|
|
@@ -58,11 +62,11 @@ module Statsample
|
|
58
62
|
#
|
59
63
|
# * number_samples: Number of new samples to add
|
60
64
|
# * n: size of each new sample. If nil, equal to original sample size
|
61
|
-
|
62
|
-
def bootstrap(number_samples,n=nil
|
65
|
+
|
66
|
+
def bootstrap(number_samples,n=nil)
|
63
67
|
number_samples.times{ |t|
|
64
68
|
@n_samples+=1
|
65
|
-
puts _("Bootstrap %d of %d") % [t+1, number_samples] if
|
69
|
+
puts _("Bootstrap %d of %d") % [t+1, number_samples] if @debug
|
66
70
|
ds_boot=@ds.bootstrap(n)
|
67
71
|
da_1=DominanceAnalysis.new(ds_boot, @y_var, :regression_class => @regression_class)
|
68
72
|
da_1.total_dominance.each{|k,v|
|
@@ -93,6 +97,7 @@ module Statsample
|
|
93
97
|
}
|
94
98
|
end
|
95
99
|
end
|
100
|
+
# Summary of analysis
|
96
101
|
def summary
|
97
102
|
rp=ReportBuilder.new()
|
98
103
|
rp.add(self)
|
@@ -101,7 +106,7 @@ module Statsample
|
|
101
106
|
def t
|
102
107
|
Distribution::T.p_value(1-((1-@alpha) / 2), @n_samples - 1)
|
103
108
|
end
|
104
|
-
def to_reportbuilder(generator)
|
109
|
+
def to_reportbuilder(generator) # :nodoc:
|
105
110
|
raise "You should bootstrap first" if @n_samples==0
|
106
111
|
anchor=generator.add_toc_entry(_("DAB: ")+@name)
|
107
112
|
generator.add_html "<div class='dominance-analysis-bootstrap'>#{@name}<a name='#{anchor}'></a>"
|
@@ -95,7 +95,7 @@ module Factor
|
|
95
95
|
}
|
96
96
|
@eigenpairs=@eigenpairs.sort.reverse
|
97
97
|
end
|
98
|
-
def to_reportbuilder(generator)
|
98
|
+
def to_reportbuilder(generator) # :nodoc:
|
99
99
|
anchor=generator.add_toc_entry(_("PCA: ")+name)
|
100
100
|
generator.add_html "<div class='pca'>"+_("PCA")+" #{@name}<a name='#{anchor}'></a>"
|
101
101
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'GDChart'
|
2
2
|
module Statsample
|
3
|
-
module Util
|
3
|
+
module Util # :nodoc:
|
4
4
|
class << self
|
5
5
|
def chart_gdchart(file,width,height,chart_type, labels, options,num_datasets,data)
|
6
6
|
require 'GDChart'
|
@@ -18,7 +18,7 @@ module Statsample
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
class Vector
|
21
|
+
class Vector # :nodoc:
|
22
22
|
# Creates a barchart using ruby-gdchart
|
23
23
|
def gdchart_frequencies(file, width=300, height=150, chart_type=GDChart::BAR, options={})
|
24
24
|
labels,data=[],[]
|
@@ -1,108 +1,108 @@
|
|
1
1
|
module Statsample
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
2
|
+
module Graph
|
3
|
+
class SvgBoxplot < SVG::Graph::Bar # :nodoc:
|
4
|
+
def initialize(config={})
|
5
|
+
config[:fields]=["dummy"]
|
6
|
+
super(config)
|
7
|
+
end
|
8
|
+
def get_x_labels
|
9
|
+
@data.collect{|d|
|
10
|
+
d[:title]
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def min_value
|
15
|
+
min = 0
|
16
|
+
if min_scale_value.nil?
|
17
|
+
min = @data.collect{|x| x[:data].min}.min
|
18
|
+
if min > 0
|
19
|
+
if min > 10
|
20
|
+
min=min-2
|
21
|
+
else
|
22
|
+
min=0
|
24
23
|
end
|
25
|
-
else
|
26
|
-
min = min_scale_value
|
27
24
|
end
|
28
|
-
|
29
|
-
|
30
|
-
def draw_data
|
31
|
-
minvalue = min_value
|
32
|
-
fieldwidth = field_width
|
33
|
-
unit_size = (@graph_height.to_f - font_size*2*top_font) /
|
34
|
-
(get_y_labels.max - get_y_labels.min)
|
35
|
-
bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0
|
36
|
-
|
37
|
-
bar_width = fieldwidth - bargap
|
38
|
-
bar_width /= @data.length if stack == :side
|
39
|
-
x_mod = (@graph_width-bargap) / 2 - (stack==:side ? bar_width/2 : 0)
|
40
|
-
|
41
|
-
bottom = @graph_height
|
42
|
-
|
43
|
-
field_count = 0
|
44
|
-
for dataset in @data
|
45
|
-
|
46
|
-
# cases (assume 0 = +ve):
|
47
|
-
# value min length
|
48
|
-
# +ve +ve value - min
|
49
|
-
# +ve -ve value - 0
|
50
|
-
# -ve -ve value.abs - 0
|
51
|
-
|
52
|
-
min=dataset[:data].min
|
53
|
-
max=dataset[:data].max
|
54
|
-
median=dataset[:vector].median
|
55
|
-
q1=dataset[:vector].percentil(25)
|
56
|
-
q3=dataset[:vector].percentil(75)
|
57
|
-
iqr=q3-q1
|
58
|
-
left = (fieldwidth * field_count)
|
59
|
-
#length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
|
60
|
-
# top is 0 if value is negative
|
61
|
-
top_wisk=(q3+iqr*1.5 < max) ? q3+iqr*1.5 : max
|
62
|
-
down_wisk= (q1-iqr*1.5 > min) ? q1-iqr*1.5 : min
|
63
|
-
|
64
|
-
top=@graph_height-((top_wisk-minvalue)*unit_size)
|
65
|
-
down=@graph_height-((down_wisk-minvalue)*unit_size)
|
66
|
-
|
67
|
-
median_bar=@graph_height-((median-minvalue)*unit_size)
|
68
|
-
middle= left+(bar_width / 2)
|
69
|
-
left_whis=left+(bar_width * 0.4)
|
70
|
-
rigth_whis=left+(bar_width*0.6)
|
71
|
-
left_rect= left+(bar_width * 0.25)
|
72
|
-
rigth_rect = left+ (bar_width * 0.75)
|
73
|
-
top_rect=@graph_height-((q3-minvalue)*unit_size)
|
74
|
-
height_rect=iqr*unit_size
|
75
|
-
path="M #{left_whis} #{top} H #{rigth_whis} M #{middle} #{top} V #{down} M #{left_whis} #{down} H #{rigth_whis} M #{left_rect} #{median_bar} H #{rigth_rect}"
|
76
|
-
|
77
|
-
|
78
|
-
# Marcamos Outliers
|
79
|
-
if top_wisk!=max or down_wisk!=min
|
80
|
-
dataset[:vector].valid_data.each{|d|
|
81
|
-
if(d<down_wisk) or (d>top_wisk)
|
82
|
-
y_out=(@graph_height - (d -minvalue)*unit_size).to_s
|
83
|
-
@graph.add_element( "circle", {
|
84
|
-
"cx" => (middle).to_s,
|
85
|
-
"cy" => y_out,
|
86
|
-
"r" => "3",
|
87
|
-
"class" => "dataPoint#{field_count+1}"
|
88
|
-
})
|
89
|
-
@graph.add_element( "text", {
|
90
|
-
"x" => (middle+20).to_s,
|
91
|
-
"y" => y_out,
|
92
|
-
"class" => "dataPointLabel",
|
93
|
-
"style" => "#{style} stroke: #000;"
|
94
|
-
}).text = d.to_s end
|
95
|
-
}
|
25
|
+
else
|
26
|
+
min = min_scale_value
|
96
27
|
end
|
97
|
-
|
98
|
-
|
28
|
+
return min
|
29
|
+
end
|
30
|
+
def draw_data
|
31
|
+
minvalue = min_value
|
32
|
+
fieldwidth = field_width
|
33
|
+
unit_size = (@graph_height.to_f - font_size*2*top_font) /
|
34
|
+
(get_y_labels.max - get_y_labels.min)
|
35
|
+
bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0
|
36
|
+
|
37
|
+
bar_width = fieldwidth - bargap
|
38
|
+
bar_width /= @data.length if stack == :side
|
39
|
+
x_mod = (@graph_width-bargap) / 2 - (stack==:side ? bar_width/2 : 0)
|
40
|
+
|
41
|
+
bottom = @graph_height
|
42
|
+
|
43
|
+
field_count = 0
|
44
|
+
for dataset in @data
|
45
|
+
|
46
|
+
# cases (assume 0 = +ve):
|
47
|
+
# value min length
|
48
|
+
# +ve +ve value - min
|
49
|
+
# +ve -ve value - 0
|
50
|
+
# -ve -ve value.abs - 0
|
51
|
+
|
52
|
+
min=dataset[:data].min
|
53
|
+
max=dataset[:data].max
|
54
|
+
median=dataset[:vector].median
|
55
|
+
q1=dataset[:vector].percentil(25)
|
56
|
+
q3=dataset[:vector].percentil(75)
|
57
|
+
iqr=q3-q1
|
58
|
+
left = (fieldwidth * field_count)
|
59
|
+
#length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
|
60
|
+
# top is 0 if value is negative
|
61
|
+
top_wisk=(q3+iqr*1.5 < max) ? q3+iqr*1.5 : max
|
62
|
+
down_wisk= (q1-iqr*1.5 > min) ? q1-iqr*1.5 : min
|
63
|
+
|
64
|
+
top=@graph_height-((top_wisk-minvalue)*unit_size)
|
65
|
+
down=@graph_height-((down_wisk-minvalue)*unit_size)
|
66
|
+
|
67
|
+
median_bar=@graph_height-((median-minvalue)*unit_size)
|
68
|
+
middle= left+(bar_width / 2)
|
69
|
+
left_whis=left+(bar_width * 0.4)
|
70
|
+
rigth_whis=left+(bar_width*0.6)
|
71
|
+
left_rect= left+(bar_width * 0.25)
|
72
|
+
rigth_rect = left+ (bar_width * 0.75)
|
73
|
+
top_rect=@graph_height-((q3-minvalue)*unit_size)
|
74
|
+
height_rect=iqr*unit_size
|
75
|
+
path="M #{left_whis} #{top} H #{rigth_whis} M #{middle} #{top} V #{down} M #{left_whis} #{down} H #{rigth_whis} M #{left_rect} #{median_bar} H #{rigth_rect}"
|
76
|
+
|
77
|
+
|
78
|
+
# Marcamos Outliers
|
79
|
+
if top_wisk!=max or down_wisk!=min
|
80
|
+
dataset[:vector].valid_data.each{|d|
|
81
|
+
if(d<down_wisk) or (d>top_wisk)
|
82
|
+
y_out=(@graph_height - (d -minvalue)*unit_size).to_s
|
83
|
+
@graph.add_element( "circle", {
|
84
|
+
"cx" => (middle).to_s,
|
85
|
+
"cy" => y_out,
|
86
|
+
"r" => "3",
|
87
|
+
"class" => "dataPoint#{field_count+1}"
|
88
|
+
})
|
89
|
+
@graph.add_element( "text", {
|
90
|
+
"x" => (middle+20).to_s,
|
91
|
+
"y" => y_out,
|
92
|
+
"class" => "dataPointLabel",
|
93
|
+
"style" => "#{style} stroke: #000;"
|
94
|
+
}).text = d.to_s end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
@graph.add_element( "rect", { "x" => left_rect.to_s, "y" => top_rect.to_s, "width" => (bar_width / 2).to_s, "height" => (height_rect).to_s, "class" => "fill#{field_count+1}"})
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
@graph.add_element("path",{"d"=>path, "style"=>"stroke:black;stroke-width:2"})
|
101
|
+
|
102
|
+
field_count += 1
|
103
|
+
end
|
104
|
+
|
106
105
|
end
|
107
106
|
end
|
107
|
+
end
|
108
108
|
end
|
@@ -92,7 +92,7 @@ end
|
|
92
92
|
# this allows rendering of svg and png on rox and gqview without problems
|
93
93
|
module SVG #:nodoc:
|
94
94
|
module Graph
|
95
|
-
class BarNoOp < Bar
|
95
|
+
class BarNoOp < Bar # :nodoc:
|
96
96
|
def get_css; SVG::Graph.get_css_standard; end
|
97
97
|
end
|
98
98
|
class BarHorizontalNoOp < BarHorizontal
|
@@ -1,111 +1,109 @@
|
|
1
1
|
module Statsample
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
2
|
+
module Graph
|
3
|
+
class SvgScatterplot < SVG::Graph::Plot # :nodoc:
|
4
|
+
attr_accessor :draw_path
|
5
|
+
def initialize(ds,config={})
|
6
|
+
super(config)
|
7
|
+
@ds=ds
|
8
|
+
set_x(@ds.fields[0])
|
9
|
+
end
|
10
|
+
def set_defaults
|
11
|
+
super
|
12
|
+
init_with(
|
13
|
+
:show_data_values => false,
|
14
|
+
:draw_path => false
|
15
|
+
)
|
16
|
+
end
|
17
|
+
def set_x(x)
|
18
|
+
@x=x
|
19
|
+
@y=@ds.fields - [x]
|
20
|
+
end
|
21
|
+
def parse
|
22
|
+
data=@y.inject({}){|a,v| a[v]=[];a}
|
23
|
+
@ds.each{|row|
|
24
|
+
@y.each{|y|
|
25
|
+
data[y]+=[row[@x],row[y]] unless row[@x].nil? or row[y].nil?
|
26
|
+
}
|
27
|
+
}
|
28
|
+
data.each{|y,d|
|
29
|
+
add_data({
|
30
|
+
:data=>d, :title=>@ds.vector_label(y)
|
31
|
+
})
|
32
|
+
}
|
33
|
+
end
|
34
|
+
def get_x_labels
|
35
|
+
values=super
|
36
|
+
values.collect{|x|
|
37
|
+
if x.is_a? Integer
|
38
|
+
x
|
39
|
+
else
|
40
|
+
sprintf("%0.2f",x).to_f
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
def get_y_labels
|
45
|
+
values=super
|
46
|
+
values.collect{|x|
|
47
|
+
if x.is_a? Integer
|
48
|
+
x
|
49
|
+
else
|
50
|
+
sprintf("%0.2f",x).to_f
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
54
|
+
def draw_data
|
55
55
|
line = 1
|
56
|
-
|
56
|
+
|
57
57
|
x_min, x_max, x_div = x_range
|
58
58
|
y_min, y_max, y_div = y_range
|
59
59
|
x_step = (@graph_width.to_f - font_size*2) / (x_max-x_min)
|
60
60
|
y_step = (@graph_height.to_f - font_size*2) / (y_max-y_min)
|
61
|
-
|
61
|
+
|
62
62
|
for data in @data
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
63
|
+
x_points = data[:data][X]
|
64
|
+
y_points = data[:data][Y]
|
65
|
+
|
66
|
+
lpath = "L"
|
67
|
+
x_start = 0
|
68
|
+
y_start = 0
|
69
|
+
x_points.each_index { |idx|
|
70
|
+
x = (x_points[idx] - x_min) * x_step
|
71
|
+
y = @graph_height - (y_points[idx] - y_min) * y_step
|
72
|
+
x_start, y_start = x,y if idx == 0
|
73
|
+
lpath << "#{x} #{y} "
|
74
|
+
}
|
75
|
+
|
76
|
+
if area_fill
|
77
|
+
@graph.add_element( "path", {
|
78
|
+
"d" => "M#{x_start} #@graph_height #{lpath} V#@graph_height Z",
|
79
|
+
"class" => "fill#{line}"
|
80
|
+
})
|
81
|
+
end
|
82
|
+
if draw_path
|
83
|
+
@graph.add_element( "path", {
|
84
|
+
"d" => "M#{x_start} #{y_start} #{lpath}",
|
85
|
+
"class" => "line#{line}"
|
86
|
+
})
|
87
|
+
end
|
88
|
+
if show_data_points || show_data_values
|
89
|
+
x_points.each_index { |idx|
|
90
|
+
x = (x_points[idx] - x_min) * x_step
|
91
|
+
y = @graph_height - (y_points[idx] - y_min) * y_step
|
92
|
+
if show_data_points
|
93
|
+
@graph.add_element( "circle", {
|
94
|
+
"cx" => x.to_s,
|
95
|
+
"cy" => y.to_s,
|
96
|
+
"r" => "2.5",
|
97
|
+
"class" => "dataPoint#{line}"
|
80
98
|
})
|
99
|
+
add_popup(x, y, format( x_points[idx], y_points[idx] )) if add_popups
|
81
100
|
end
|
82
|
-
if
|
83
|
-
|
84
|
-
"d" => "M#{x_start} #{y_start} #{lpath}",
|
85
|
-
"class" => "line#{line}"
|
86
|
-
})
|
87
|
-
end
|
88
|
-
if show_data_points || show_data_values
|
89
|
-
x_points.each_index { |idx|
|
90
|
-
x = (x_points[idx] - x_min) * x_step
|
91
|
-
y = @graph_height - (y_points[idx] - y_min) * y_step
|
92
|
-
if show_data_points
|
93
|
-
@graph.add_element( "circle", {
|
94
|
-
"cx" => x.to_s,
|
95
|
-
"cy" => y.to_s,
|
96
|
-
"r" => "2.5",
|
97
|
-
"class" => "dataPoint#{line}"
|
98
|
-
})
|
99
|
-
add_popup(x, y, format( x_points[idx], y_points[idx] )) if add_popups
|
100
|
-
end
|
101
|
-
make_datapoint_text( x, y-6, y_points[idx] ) if show_data_values
|
102
|
-
}
|
103
|
-
end
|
104
|
-
line += 1
|
101
|
+
make_datapoint_text( x, y-6, y_points[idx] ) if show_data_values
|
102
|
+
}
|
105
103
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
line += 1
|
109
105
|
end
|
106
|
+
end
|
110
107
|
end
|
108
|
+
end
|
111
109
|
end
|