charty 0.1.5.dev → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,98 +1,106 @@
1
- require 'gruff'
1
+ require 'fileutils'
2
2
 
3
3
  module Charty
4
- class Gruff < PlotterAdapter
5
- Name = "gruff"
4
+ module Backends
5
+ class Gruff
6
+ Backends.register(:gruff, self)
6
7
 
7
- def initialize
8
- @plot = ::Gruff
9
- end
8
+ class << self
9
+ def prepare
10
+ require 'gruff'
11
+ end
12
+ end
10
13
 
11
- def label(x, y)
12
- end
14
+ def initialize
15
+ @plot = ::Gruff
16
+ end
13
17
 
14
- def series=(series)
15
- @series = series
16
- end
18
+ def label(x, y)
19
+ end
17
20
 
18
- def render_layout(layout)
19
- raise NotImplementedError
20
- end
21
+ def series=(series)
22
+ @series = series
23
+ end
21
24
 
22
- def render(context, filename="")
23
- FileUtils.mkdir_p(File.dirname(filename))
24
- plot(@plot, context).write(filename)
25
- end
25
+ def render_layout(layout)
26
+ raise NotImplementedError
27
+ end
28
+
29
+ def render(context, filename="")
30
+ FileUtils.mkdir_p(File.dirname(filename))
31
+ plot(@plot, context).write(filename)
32
+ end
26
33
 
27
- def plot(plot, context)
28
- # case
29
- # when plot.respond_to?(:xlim)
30
- # plot.xlim(context.range_x.begin, context.range_x.end)
31
- # plot.ylim(context.range_y.begin, context.range_y.end)
32
- # when plot.respond_to?(:set_xlim)
33
- # plot.set_xlim(context.range_x.begin, context.range_x.end)
34
- # plot.set_ylim(context.range_y.begin, context.range_y.end)
35
- # end
34
+ def plot(plot, context)
35
+ # case
36
+ # when plot.respond_to?(:xlim)
37
+ # plot.xlim(context.range_x.begin, context.range_x.end)
38
+ # plot.ylim(context.range_y.begin, context.range_y.end)
39
+ # when plot.respond_to?(:set_xlim)
40
+ # plot.set_xlim(context.range_x.begin, context.range_x.end)
41
+ # plot.set_ylim(context.range_y.begin, context.range_y.end)
42
+ # end
36
43
 
37
- case context.method
38
- when :bar
39
- p = plot::Bar.new
40
- p.title = context.title if context.title
41
- p.x_axis_label = context.xlabel if context.xlabel
42
- p.y_axis_label = context.ylabel if context.ylabel
43
- context.series.each do |data|
44
- p.data(data.label, data.xs.to_a)
45
- end
46
- p
47
- when :barh
48
- p = plot::SideBar.new
49
- p.title = context.title if context.title
50
- p.x_axis_label = context.xlabel if context.xlabel
51
- p.y_axis_label = context.ylabel if context.ylabel
52
- labels = context.series.map {|data| data.xs.to_a}.flatten.uniq
53
- labels.each do |label|
54
- data_ys = context.series.map do |data|
55
- if data.xs.to_a.index(label)
56
- data.ys.to_a[data.xs.to_a.index(label)]
57
- else
58
- 0
44
+ case context.method
45
+ when :bar
46
+ p = plot::Bar.new
47
+ p.title = context.title if context.title
48
+ p.x_axis_label = context.xlabel if context.xlabel
49
+ p.y_axis_label = context.ylabel if context.ylabel
50
+ context.series.each do |data|
51
+ p.data(data.label, data.xs.to_a)
52
+ end
53
+ p
54
+ when :barh
55
+ p = plot::SideBar.new
56
+ p.title = context.title if context.title
57
+ p.x_axis_label = context.xlabel if context.xlabel
58
+ p.y_axis_label = context.ylabel if context.ylabel
59
+ labels = context.series.map {|data| data.xs.to_a}.flatten.uniq
60
+ labels.each do |label|
61
+ data_ys = context.series.map do |data|
62
+ if data.xs.to_a.index(label)
63
+ data.ys.to_a[data.xs.to_a.index(label)]
64
+ else
65
+ 0
66
+ end
59
67
  end
68
+ p.data(label, data_ys)
60
69
  end
61
- p.data(label, data_ys)
62
- end
63
- p.labels = context.series.each_with_index.inject({}) do |attr, (data, i)|
64
- attr[i] = data.label
65
- attr
66
- end
67
- p
68
- when :box_plot
69
- # refs. https://github.com/topfunky/gruff/issues/155
70
- raise NotImplementedError
71
- when :bubble
72
- raise NotImplementedError
73
- when :curve
74
- p = plot::Line.new
75
- p.title = context.title if context.title
76
- p.x_axis_label = context.xlabel if context.xlabel
77
- p.y_axis_label = context.ylabel if context.ylabel
78
- context.series.each do |data|
79
- p.data(data.label, data.xs.to_a)
80
- end
81
- p
82
- when :scatter
83
- p = plot::Scatter.new
84
- p.title = context.title if context.title
85
- p.x_axis_label = context.xlabel if context.xlabel
86
- p.y_axis_label = context.ylabel if context.ylabel
87
- context.series.each do |data|
88
- p.data(data.label, data.xs.to_a, data.ys.to_a)
70
+ p.labels = context.series.each_with_index.inject({}) do |attr, (data, i)|
71
+ attr[i] = data.label
72
+ attr
73
+ end
74
+ p
75
+ when :box_plot
76
+ # refs. https://github.com/topfunky/gruff/issues/155
77
+ raise NotImplementedError
78
+ when :bubble
79
+ raise NotImplementedError
80
+ when :curve
81
+ p = plot::Line.new
82
+ p.title = context.title if context.title
83
+ p.x_axis_label = context.xlabel if context.xlabel
84
+ p.y_axis_label = context.ylabel if context.ylabel
85
+ context.series.each do |data|
86
+ p.data(data.label, data.xs.to_a)
87
+ end
88
+ p
89
+ when :scatter
90
+ p = plot::Scatter.new
91
+ p.title = context.title if context.title
92
+ p.x_axis_label = context.xlabel if context.xlabel
93
+ p.y_axis_label = context.ylabel if context.ylabel
94
+ context.series.each do |data|
95
+ p.data(data.label, data.xs.to_a, data.ys.to_a)
96
+ end
97
+ p
98
+ when :error_bar
99
+ # refs. https://github.com/topfunky/gruff/issues/163
100
+ raise NotImplementedError
101
+ when :hist
102
+ raise NotImplementedError
89
103
  end
90
- p
91
- when :error_bar
92
- # refs. https://github.com/topfunky/gruff/issues/163
93
- raise NotImplementedError
94
- when :hist
95
- raise NotImplementedError
96
104
  end
97
105
  end
98
106
  end
@@ -0,0 +1,109 @@
1
+ require 'json'
2
+
3
+ module Charty
4
+ module Backends
5
+ class Plotly
6
+ Backends.register(:plotly, self)
7
+
8
+ attr_reader :context
9
+
10
+ class << self
11
+ attr_writer :chart_id, :with_api_load_tag, :plotly_src
12
+
13
+ def chart_id
14
+ @chart_id ||= 0
15
+ end
16
+
17
+ def with_api_load_tag
18
+ return @with_api_load_tag unless @with_api_load_tag.nil?
19
+
20
+ @with_api_load_tag = true
21
+ end
22
+
23
+ def plotly_src
24
+ @plotly_src ||= 'https://cdn.plot.ly/plotly-latest.min.js'
25
+ end
26
+ end
27
+
28
+ def initilize
29
+ end
30
+
31
+ def label(x, y)
32
+ end
33
+
34
+ def series=(series)
35
+ @series = series
36
+ end
37
+
38
+ def render(context, filename)
39
+ plot(nil, context)
40
+ end
41
+
42
+ def plot(plot, context)
43
+ context = context
44
+ self.class.chart_id += 1
45
+
46
+ case context.method
47
+ when :bar
48
+ render_graph(context, :bar)
49
+ when :curve
50
+ render_graph(context, :scatter)
51
+ when :scatter
52
+ render_graph(context, nil, options: {data: {mode: "markers"}})
53
+ else
54
+ raise NotImplementedError
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def plotly_load_tag
61
+ if self.class.with_api_load_tag
62
+ "<script type='text/javascript' src='#{self.class.plotly_src}'></script>"
63
+ else
64
+ end
65
+ end
66
+
67
+ def div_id
68
+ "charty-plotly-#{self.class.chart_id}"
69
+ end
70
+
71
+ def div_style
72
+ "width: 100%;height: 100%;"
73
+ end
74
+
75
+ def render_graph(context, type, options: {})
76
+ data = context.series.map do |series|
77
+ {
78
+ type: type,
79
+ x: series.xs.to_a,
80
+ y: series.ys.to_a,
81
+ name: series.label
82
+ }.merge(options[:data] || {})
83
+ end
84
+ layout = {
85
+ title: { text: context.title },
86
+ xaxis: {
87
+ title: context.xlabel,
88
+ range: [context.range[:x].first, context.range[:x].last]
89
+ },
90
+ yaxis: {
91
+ title: context.ylabel,
92
+ range: [context.range[:y].first, context.range[:y].last]
93
+ }
94
+ }
95
+ render_html(data, layout)
96
+ end
97
+
98
+ def render_html(data, layout)
99
+ <<~FRAGMENT
100
+ #{plotly_load_tag unless self.class.chart_id > 1}
101
+ <div id="#{div_id}" style="#{div_style}"></div>
102
+ <script>
103
+ Plotly.plot('#{div_id}', #{JSON.dump(data)}, #{JSON.dump(layout)} );
104
+ </script>
105
+ FRAGMENT
106
+ end
107
+ end
108
+ end
109
+ end
@@ -1,109 +1,117 @@
1
- require 'matplotlib/pyplot'
1
+ require 'fileutils'
2
2
 
3
3
  module Charty
4
- class PyPlot < PlotterAdapter
5
- Name = "pyplot"
4
+ module Backends
5
+ class Pyplot
6
+ Backends.register(:pyplot, self)
6
7
 
7
- def initialize
8
- @plot = Matplotlib::Pyplot
9
- end
10
-
11
- def self.activate_iruby_integration
12
- require 'matplotlib/iruby'
13
- Matplotlib::IRuby.activate
14
- end
15
-
16
- def label(x, y)
17
- end
18
-
19
- def series=(series)
20
- @series = series
21
- end
22
-
23
- def render_layout(layout)
24
- (fig, axes) = *@plot.subplots(nrows: layout.num_rows, ncols: layout.num_cols)
25
- layout.rows.each_with_index do |row, y|
26
- row.each_with_index do |cel, x|
27
- plot = layout.num_rows > 1 ? axes[y][x] : axes[x]
28
- plot(plot, cel, subplot: true)
8
+ class << self
9
+ def prepare
10
+ require 'matplotlib/pyplot'
29
11
  end
30
12
  end
31
- @plot.show
32
- end
33
13
 
34
- def render(context, filename)
35
- plot(@plot, context)
36
- if filename
37
- FileUtils.mkdir_p(File.dirname(filename))
38
- @plot.savefig(filename)
14
+ def initialize
15
+ @plot = ::Matplotlib::Pyplot
39
16
  end
40
- @plot.show
41
- end
42
17
 
43
- def save(context, filename)
44
- plot(@plot, context)
45
- if filename
46
- FileUtils.mkdir_p(File.dirname(filename))
47
- @plot.savefig(filename)
18
+ def self.activate_iruby_integration
19
+ require 'matplotlib/iruby'
20
+ ::Matplotlib::IRuby.activate
48
21
  end
49
- end
50
22
 
51
- def plot(plot, context, subplot: false)
52
- # TODO: Since it is not required, research and change conditions.
53
- # case
54
- # when plot.respond_to?(:xlim)
55
- # plot.xlim(context.range_x.begin, context.range_x.end)
56
- # plot.ylim(context.range_y.begin, context.range_y.end)
57
- # when plot.respond_to?(:set_xlim)
58
- # plot.set_xlim(context.range_x.begin, context.range_x.end)
59
- # plot.set_ylim(context.range_y.begin, context.range_y.end)
60
- # end
23
+ def label(x, y)
24
+ end
61
25
 
62
- plot.title(context.title) if context.title
63
- if !subplot
64
- plot.xlabel(context.xlabel) if context.xlabel
65
- plot.ylabel(context.ylabel) if context.ylabel
26
+ def series=(series)
27
+ @series = series
66
28
  end
67
29
 
68
- case context.method
69
- when :bar
70
- context.series.each do |data|
71
- plot.bar(data.xs.to_a.map(&:to_s), data.ys.to_a, label: data.label)
72
- end
73
- plot.legend()
74
- when :barh
75
- context.series.each do |data|
76
- plot.barh(data.xs.to_a.map(&:to_s), data.ys.to_a)
30
+ def render_layout(layout)
31
+ _fig, axes = @plot.subplots(nrows: layout.num_rows, ncols: layout.num_cols)
32
+ layout.rows.each_with_index do |row, y|
33
+ row.each_with_index do |cel, x|
34
+ plot = layout.num_rows > 1 ? axes[y][x] : axes[x]
35
+ plot(plot, cel, subplot: true)
36
+ end
77
37
  end
78
- when :box_plot
79
- plot.boxplot(context.data.to_a, labels: context.labels)
80
- when :bubble
81
- context.series.each do |data|
82
- plot.scatter(data.xs.to_a, data.ys.to_a, s: data.zs.to_a, alpha: 0.5, label: data.label)
38
+ @plot.show
39
+ end
40
+
41
+ def render(context, filename)
42
+ plot(@plot, context)
43
+ if filename
44
+ FileUtils.mkdir_p(File.dirname(filename))
45
+ @plot.savefig(filename)
83
46
  end
84
- plot.legend()
85
- when :curve
86
- context.series.each do |data|
87
- plot.plot(data.xs.to_a, data.ys.to_a)
47
+ @plot.show
48
+ end
49
+
50
+ def save(context, filename)
51
+ plot(@plot, context)
52
+ if filename
53
+ FileUtils.mkdir_p(File.dirname(filename))
54
+ @plot.savefig(filename)
88
55
  end
89
- when :scatter
90
- context.series.each do |data|
91
- plot.scatter(data.xs.to_a, data.ys.to_a, label: data.label)
56
+ end
57
+
58
+ def plot(plot, context, subplot: false)
59
+ # TODO: Since it is not required, research and change conditions.
60
+ # case
61
+ # when plot.respond_to?(:xlim)
62
+ # plot.xlim(context.range_x.begin, context.range_x.end)
63
+ # plot.ylim(context.range_y.begin, context.range_y.end)
64
+ # when plot.respond_to?(:set_xlim)
65
+ # plot.set_xlim(context.range_x.begin, context.range_x.end)
66
+ # plot.set_ylim(context.range_y.begin, context.range_y.end)
67
+ # end
68
+
69
+ plot.title(context.title) if context.title
70
+ if !subplot
71
+ plot.xlabel(context.xlabel) if context.xlabel
72
+ plot.ylabel(context.ylabel) if context.ylabel
92
73
  end
93
- plot.legend()
94
- when :error_bar
95
- context.series.each do |data|
96
- plot.errorbar(
97
- data.xs.to_a,
98
- data.ys.to_a,
99
- data.xerr,
100
- data.yerr,
101
- label: data.label,
102
- )
74
+
75
+ case context.method
76
+ when :bar
77
+ context.series.each do |data|
78
+ plot.bar(data.xs.to_a.map(&:to_s), data.ys.to_a, label: data.label)
79
+ end
80
+ plot.legend()
81
+ when :barh
82
+ context.series.each do |data|
83
+ plot.barh(data.xs.to_a.map(&:to_s), data.ys.to_a)
84
+ end
85
+ when :box_plot
86
+ plot.boxplot(context.data.to_a, labels: context.labels)
87
+ when :bubble
88
+ context.series.each do |data|
89
+ plot.scatter(data.xs.to_a, data.ys.to_a, s: data.zs.to_a, alpha: 0.5, label: data.label)
90
+ end
91
+ plot.legend()
92
+ when :curve
93
+ context.series.each do |data|
94
+ plot.plot(data.xs.to_a, data.ys.to_a)
95
+ end
96
+ when :scatter
97
+ context.series.each do |data|
98
+ plot.scatter(data.xs.to_a, data.ys.to_a, label: data.label)
99
+ end
100
+ plot.legend()
101
+ when :error_bar
102
+ context.series.each do |data|
103
+ plot.errorbar(
104
+ data.xs.to_a,
105
+ data.ys.to_a,
106
+ data.xerr,
107
+ data.yerr,
108
+ label: data.label,
109
+ )
110
+ end
111
+ plot.legend()
112
+ when :hist
113
+ plot.hist(context.data.to_a)
103
114
  end
104
- plot.legend()
105
- when :hist
106
- plot.hist(context.data.to_a)
107
115
  end
108
116
  end
109
117
  end