charma 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Charma
4
+ class ViolinChart < Chart
5
+ def initialize(opts)
6
+ super(opts)
7
+ end
8
+
9
+ # TODO: LineChart に同じようなメソッドがあるのでなんとかする
10
+ def calc_range(sym)
11
+ r0 = @opts[:series].map{ |e| e[sym] }.flatten.minmax
12
+ dist = r0[1] - r0[0]
13
+ delta = dist==0 ? 1 : dist*0.1
14
+ raw_range =
15
+ if 0<=r0[0]
16
+ [[r0[0]-delta, 0].max, r0[1]+delta]
17
+ else
18
+ [r0[0]-delta, r0[1]+delta]
19
+ end
20
+ raw_range.map{ |e| unscale_value( sym, e ) }
21
+ end
22
+
23
+ # TODO: BarChart に同じメソッドがあるのでなんとかする
24
+ def render_xticks(pdf, area)
25
+ rects = area.hsplit(*Array.new(@opts[:x_ticks].size){ 1 }).map{ |rc0|
26
+ rc0.hsplit(1,8,1)[1]
27
+ }
28
+ draw_samesize_texts( pdf, rects, @opts[:x_ticks], valign: :top )
29
+ end
30
+
31
+ def draw_violin(pdf, rect, yrange, hists, cols)
32
+ ratio = 0.75
33
+ _, violins, = rect.hsplit( (1-ratio)/2, ratio, (1-ratio)/2 )
34
+ v_rects = violins.hsplit(*Array.new(hists.size,1))
35
+ v_rects.zip(hists, cols) do |rc, hist, col|
36
+ cx = rc.x + rc.w/2
37
+ h = rc.h / hist.size.to_f
38
+ hist.each.with_index do |f, ix|
39
+ w = rc.w * f
40
+ top = rc.bottom + h*(ix+1)
41
+ edge = 1e-1 # バーの隙間を埋める
42
+ fill_rect( pdf, Rect.new( cx-w/2, top + edge, w, h + edge*2 ), col )
43
+ end
44
+ end
45
+ end
46
+
47
+ def meansize( vals )
48
+ sum=0.0
49
+ count=0
50
+ vals.each do |vvv|
51
+ vvv.each do |vv|
52
+ sum += vv.size
53
+ count+=1
54
+ end
55
+ end
56
+ sum / count
57
+ end
58
+
59
+ def make_histograms( vals, range )
60
+ hist_size = [10,Math.sqrt( meansize(vals) ).round].max
61
+ min = range.min
62
+ step = (range.max - min).to_f / hist_size
63
+ bottoms = Array.new(hist_size){ |ix| min + (ix+1)*step }
64
+ raw_h = vals.map{ |vvv|
65
+ vvv.map{ |vv|
66
+ vv.each.with_object([0]*hist_size){ |v,o|
67
+ ix = bottoms.index{ |b| v<b }
68
+ o[ix]+=1
69
+ }
70
+ }
71
+ }
72
+ ratio = 1.0 / raw_h.flatten.max
73
+ raw_h.map{ |vvv|
74
+ vvv.map{ |vv|
75
+ vv.map{ |e| e*ratio }
76
+ }
77
+ }
78
+ end
79
+
80
+ def render_chart(pdf, rect, yrange)
81
+ y_values = @opts[:series].map{ |s| s[:y] }.transpose
82
+ bar_areas = rect.hsplit(*Array.new(y_values.size,1))
83
+ cols = if y_values.first.size==1
84
+ colors(y_values.size).map{ |e| [e] }
85
+ else
86
+ [colors(y_values.first.size)] * y_values.size
87
+ end
88
+ hists = make_histograms(y_values, yrange)
89
+ hists.zip(bar_areas, cols).each do |h, rc, c|
90
+ draw_violin(pdf, rc, yrange, h, c)
91
+ end
92
+ end
93
+
94
+ # BarChart の render とほぼ同じなのでなんとかする
95
+ def render( pdf, rect )
96
+ stroke_rect(pdf, rect)
97
+ title_text = @opts[:title]
98
+ title, main, ticks, bottom = rect.vsplit(
99
+ (title_text ? 1 : 0),
100
+ 7,
101
+ (@opts[:x_ticks] ? 0.5 : 0),
102
+ (bottom_legend? ? 0.5 : 0))
103
+ draw_text( pdf, title, title_text ) if title_text
104
+ hratio = [(@opts[:y_label] ? 1 : 0), 1, 10]
105
+ ylabel, yticks, chart = main.hsplit(*hratio)
106
+ yrange = @opts[:y_range] || calc_range(:y)
107
+ render_chart(pdf, chart, yrange)
108
+ if @opts[:y_label]
109
+ render_rottext(pdf, ylabel, @opts[:y_label] )
110
+ end
111
+ if @opts[:x_ticks]
112
+ _, _, xticks = ticks.hsplit(*hratio)
113
+ render_xticks(pdf, xticks)
114
+ end
115
+ yvalues = tick_values(:y, yrange)
116
+ render_yticks(pdf, yticks, yrange, yvalues)
117
+ render_y_grid(pdf, chart, yrange, yvalues)
118
+ render_legend(pdf, bottom) if bottom_legend?
119
+ end
120
+ end
121
+ end
data/lib/charma.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prawn"
4
+ require_relative "charma/version"
5
+ require_relative "charma/error"
6
+ require_relative "charma/rect"
7
+ require_relative "charma/chart"
8
+
9
+ require_relative "charma/bar_chart"
10
+ require_relative "charma/line_chart"
11
+ require_relative "charma/violin_chart"
12
+
13
+ require_relative "charma/page"
14
+ require_relative "charma/document"
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: charma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nabetani
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prawn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: Create chart in PDF
84
+ email:
85
+ - takenori@nabetani.sakura.ne.jp
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".rubocop.yml"
93
+ - ".travis.yml"
94
+ - CODE_OF_CONDUCT.md
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/console
101
+ - bin/setup
102
+ - charma.gemspec
103
+ - examples/bar_charts.pdf
104
+ - examples/bar_charts.rb
105
+ - examples/line_charts.pdf
106
+ - examples/line_charts.rb
107
+ - examples/runall.rb
108
+ - examples/violin_charts.pdf
109
+ - examples/violin_charts.rb
110
+ - lib/charma.rb
111
+ - lib/charma/bar_chart.rb
112
+ - lib/charma/chart.rb
113
+ - lib/charma/document.rb
114
+ - lib/charma/error.rb
115
+ - lib/charma/line_chart.rb
116
+ - lib/charma/page.rb
117
+ - lib/charma/rect.rb
118
+ - lib/charma/version.rb
119
+ - lib/charma/violin_chart.rb
120
+ homepage: https://github.com/nabetani/charma
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubygems_version: 3.0.3
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Create chart in PDF
143
+ test_files: []