charty 0.1.5.dev → 0.2.0

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.
@@ -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