statsample 0.6.2 → 0.6.3
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/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
|