charty 0.2.5 → 0.2.6
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.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/charty.gemspec +8 -5
- data/lib/charty.rb +2 -2
- data/lib/charty/backends/plotly.rb +197 -8
- data/lib/charty/backends/pyplot.rb +135 -44
- data/lib/charty/dash_pattern_generator.rb +57 -0
- data/lib/charty/index.rb +1 -1
- data/lib/charty/plot_methods.rb +73 -3
- data/lib/charty/plotters.rb +1 -0
- data/lib/charty/plotters/abstract_plotter.rb +69 -9
- data/lib/charty/plotters/line_plotter.rb +300 -0
- data/lib/charty/plotters/relational_plotter.rb +213 -96
- data/lib/charty/plotters/scatter_plotter.rb +7 -31
- data/lib/charty/statistics.rb +2 -2
- data/lib/charty/table.rb +124 -14
- data/lib/charty/table_adapters/base_adapter.rb +97 -0
- data/lib/charty/table_adapters/daru_adapter.rb +2 -0
- data/lib/charty/table_adapters/datasets_adapter.rb +7 -0
- data/lib/charty/table_adapters/hash_adapter.rb +13 -2
- data/lib/charty/table_adapters/pandas_adapter.rb +82 -0
- data/lib/charty/util.rb +8 -0
- data/lib/charty/vector_adapters.rb +5 -1
- data/lib/charty/vector_adapters/array_adapter.rb +2 -10
- data/lib/charty/vector_adapters/daru_adapter.rb +3 -11
- data/lib/charty/vector_adapters/narray_adapter.rb +1 -6
- data/lib/charty/vector_adapters/numpy_adapter.rb +1 -1
- data/lib/charty/vector_adapters/pandas_adapter.rb +0 -1
- data/lib/charty/version.rb +1 -1
- metadata +54 -25
- data/lib/charty/missing_value_support.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63e13663e8213e077993e52b906b630c35a1f7f9a224abb99fd206bb700659c2
|
4
|
+
data.tar.gz: d7fd53056c32c18bf5af6b1e1a4b2a29bfe652a427b338087d3cab538a0797ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc4da146432f688eb52dd382ea516e02ab84ef7143453c80fa5bc14fef55851728550ee58fe98c1c3a5e9a1eac0f33dcfb702356bc7c0f344ceaf85f87400435
|
7
|
+
data.tar.gz: f519610073317c3fafd42b97ad5e96d124265f6a7d79a54023995cf82d1fe84624d4f914c26e3eef644ad280110400fe1cdac275ec5e32145d7e4b652ef47891
|
data/README.md
CHANGED
@@ -100,7 +100,8 @@ Charty::Backends.use(:plotly) # select plotly backend
|
|
100
100
|
plot.save("scatter.html") # save the plot as an HTML file
|
101
101
|
```
|
102
102
|
|
103
|
-
|
103
|
+
When you already have prepared [playwright-ruby-client](https://github.com/YusukeIwaki/playwright-ruby-client),
|
104
|
+
you can render a plot into a PNG file by plotly backend by specifying a filename with `.png` extension.
|
104
105
|
|
105
106
|
```ruby
|
106
107
|
plot.save("scatter.png")
|
data/charty.gemspec
CHANGED
@@ -26,17 +26,20 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
|
-
spec.add_dependency "red-colors"
|
30
|
-
spec.add_dependency "red-palette", ">= 0.
|
29
|
+
spec.add_dependency "red-colors", ">= 0.3.0"
|
30
|
+
spec.add_dependency "red-palette", ">= 0.5.0"
|
31
|
+
|
32
|
+
spec.add_dependency "matplotlib", ">= 1.2.0"
|
33
|
+
spec.add_dependency "pandas", ">= 0.3.5"
|
34
|
+
spec.add_dependency "playwright-ruby-client"
|
31
35
|
|
32
36
|
spec.add_development_dependency "bundler", ">= 1.16"
|
33
37
|
spec.add_development_dependency "rake"
|
34
38
|
spec.add_development_dependency "test-unit"
|
35
|
-
spec.add_development_dependency "red-datasets", ">= 0.
|
39
|
+
spec.add_development_dependency "red-datasets", ">= 0.1.2"
|
36
40
|
spec.add_development_dependency "daru"
|
37
41
|
spec.add_development_dependency "matrix" # need for daru on Ruby > 3.0
|
38
42
|
spec.add_development_dependency "activerecord"
|
39
43
|
spec.add_development_dependency "sqlite3"
|
40
|
-
spec.add_development_dependency "
|
41
|
-
spec.add_development_dependency "iruby"
|
44
|
+
spec.add_development_dependency "iruby", ">= 0.7.0"
|
42
45
|
end
|
data/lib/charty.rb
CHANGED
@@ -4,17 +4,17 @@ require "colors"
|
|
4
4
|
require "palette"
|
5
5
|
|
6
6
|
require_relative "charty/util"
|
7
|
+
require_relative "charty/dash_pattern_generator"
|
7
8
|
require_relative "charty/backends"
|
8
9
|
require_relative "charty/backend_methods"
|
9
10
|
require_relative "charty/plotter"
|
10
11
|
require_relative "charty/index"
|
11
12
|
require_relative "charty/layout"
|
12
13
|
require_relative "charty/linspace"
|
13
|
-
require_relative "charty/missing_value_support"
|
14
14
|
require_relative "charty/plotters"
|
15
15
|
require_relative "charty/plot_methods"
|
16
|
-
require_relative "charty/table_adapters"
|
17
16
|
require_relative "charty/table"
|
17
|
+
require_relative "charty/table_adapters"
|
18
18
|
require_relative "charty/statistics"
|
19
19
|
require_relative "charty/vector_adapters"
|
20
20
|
require_relative "charty/vector"
|
@@ -248,12 +248,8 @@ module Charty
|
|
248
248
|
@traces.concat(traces)
|
249
249
|
end
|
250
250
|
|
251
|
-
def scatter(x, y, variables,
|
251
|
+
def scatter(x, y, variables, color:, color_mapper:,
|
252
252
|
style:, style_mapper:, size:, size_mapper:)
|
253
|
-
if legend == :full
|
254
|
-
warn("Plotly backend does not support full verbosity legend")
|
255
|
-
end
|
256
|
-
|
257
253
|
orig_x, orig_y = x, y
|
258
254
|
|
259
255
|
x = case x
|
@@ -277,7 +273,7 @@ module Charty
|
|
277
273
|
end
|
278
274
|
|
279
275
|
unless color.nil? && style.nil?
|
280
|
-
grouped_scatter(x, y, variables,
|
276
|
+
grouped_scatter(x, y, variables,
|
281
277
|
color: color, color_mapper: color_mapper,
|
282
278
|
style: style, style_mapper: style_mapper,
|
283
279
|
size: size, size_mapper: size_mapper)
|
@@ -305,7 +301,7 @@ module Charty
|
|
305
301
|
@traces << trace
|
306
302
|
end
|
307
303
|
|
308
|
-
private def grouped_scatter(x, y, variables,
|
304
|
+
private def grouped_scatter(x, y, variables, color:, color_mapper:,
|
309
305
|
style:, style_mapper:, size:, size_mapper:)
|
310
306
|
@layout[:showlegend] = true
|
311
307
|
|
@@ -333,7 +329,9 @@ module Charty
|
|
333
329
|
|
334
330
|
unless size.nil?
|
335
331
|
vals = size.values_at(*indices)
|
336
|
-
trace[:marker][:size] = size_mapper[vals].map
|
332
|
+
trace[:marker][:size] = size_mapper[vals].map do |x|
|
333
|
+
scale_scatter_point_size(x).to_f
|
334
|
+
end
|
337
335
|
end
|
338
336
|
|
339
337
|
name = []
|
@@ -362,6 +360,12 @@ module Charty
|
|
362
360
|
end
|
363
361
|
end
|
364
362
|
|
363
|
+
def add_scatter_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
|
364
|
+
if legend == :full
|
365
|
+
warn("Plotly backend does not support full verbosity legend")
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
365
369
|
private def scale_scatter_point_size(x)
|
366
370
|
min = 6
|
367
371
|
max = 12
|
@@ -369,6 +373,191 @@ module Charty
|
|
369
373
|
min + x * (max - min)
|
370
374
|
end
|
371
375
|
|
376
|
+
def line(x, y, variables, color:, color_mapper:, size:, size_mapper:, style:, style_mapper:, ci_params:)
|
377
|
+
x = case x
|
378
|
+
when Charty::Vector
|
379
|
+
x.to_a
|
380
|
+
else
|
381
|
+
orig_x, x = x, Array.try_convert(x)
|
382
|
+
if x.nil?
|
383
|
+
raise ArgumentError, "Invalid value for x: %p" % orig_x
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
y = case y
|
388
|
+
when Charty::Vector
|
389
|
+
y.to_a
|
390
|
+
else
|
391
|
+
orig_y, y = y, Array.try_convert(y)
|
392
|
+
if y.nil?
|
393
|
+
raise ArgumentError, "Invalid value for y: %p" % orig_y
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
name = []
|
398
|
+
legend_title = []
|
399
|
+
|
400
|
+
if color.nil?
|
401
|
+
# TODO: do not hard code this
|
402
|
+
line_color = Colors["#1f77b4"] # the first color of D3's category10 palette
|
403
|
+
else
|
404
|
+
line_color = color_mapper[color].to_rgb
|
405
|
+
name << color
|
406
|
+
legend_title << variables[:color]
|
407
|
+
end
|
408
|
+
|
409
|
+
unless style.nil?
|
410
|
+
marker, dashes = style_mapper[style].values_at(:marker, :dashes)
|
411
|
+
name << style
|
412
|
+
legend_title << variables[:style]
|
413
|
+
end
|
414
|
+
|
415
|
+
trace = {
|
416
|
+
type: :scatter,
|
417
|
+
mode: marker.nil? ? "lines" : "lines+markers",
|
418
|
+
x: x,
|
419
|
+
y: y,
|
420
|
+
line: {
|
421
|
+
shape: :linear,
|
422
|
+
color: line_color.to_hex_string
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
default_line_width = 2.0
|
427
|
+
unless size.nil?
|
428
|
+
line_width = default_line_width + 2.0 * size_mapper[size]
|
429
|
+
trace[:line][:width] = line_width
|
430
|
+
end
|
431
|
+
|
432
|
+
unless dashes.nil?
|
433
|
+
trace[:line][:dash] = convert_dash_pattern(dashes, line_width || default_line_width)
|
434
|
+
end
|
435
|
+
|
436
|
+
unless marker.nil?
|
437
|
+
trace[:marker] = {
|
438
|
+
line: {
|
439
|
+
width: 1,
|
440
|
+
color: "#fff"
|
441
|
+
},
|
442
|
+
symbol: marker,
|
443
|
+
size: 10
|
444
|
+
}
|
445
|
+
end
|
446
|
+
|
447
|
+
unless ci_params.nil?
|
448
|
+
case ci_params[:style]
|
449
|
+
when :band
|
450
|
+
y_min = ci_params[:y_min].to_a
|
451
|
+
y_max = ci_params[:y_max].to_a
|
452
|
+
@traces << {
|
453
|
+
type: :scatter,
|
454
|
+
x: x,
|
455
|
+
y: y_max,
|
456
|
+
mode: :lines,
|
457
|
+
line: { shape: :linear, width: 0 },
|
458
|
+
showlegend: false
|
459
|
+
}
|
460
|
+
@traces << {
|
461
|
+
type: :scatter,
|
462
|
+
x: x,
|
463
|
+
y: y_min,
|
464
|
+
mode: :lines,
|
465
|
+
line: { shape: :linear, width: 0 },
|
466
|
+
fill: :tonexty,
|
467
|
+
fillcolor: line_color.to_rgba(alpha: 0.2).to_hex_string,
|
468
|
+
showlegend: false
|
469
|
+
}
|
470
|
+
when :bars
|
471
|
+
y_min = ci_params[:y_min].map.with_index {|v, i| y[i] - v }
|
472
|
+
y_max = ci_params[:y_max].map.with_index {|v, i| v - y[i] }
|
473
|
+
trace[:error_y] = {
|
474
|
+
visible: true,
|
475
|
+
type: :data,
|
476
|
+
array: y_max,
|
477
|
+
arrayminus: y_min
|
478
|
+
}
|
479
|
+
unless line_color.nil?
|
480
|
+
trace[:error_y][:color] = line_color
|
481
|
+
end
|
482
|
+
unless line_width.nil?
|
483
|
+
trace[:error_y][:thickness] = line_width
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
trace[:name] = name.uniq.join(", ") unless name.empty?
|
489
|
+
|
490
|
+
@traces << trace
|
491
|
+
|
492
|
+
unless legend_title.empty?
|
493
|
+
@layout[:showlegend] = true
|
494
|
+
@layout[:legend] ||= {}
|
495
|
+
@layout[:legend][:title] = {text: legend_title.uniq.join(", ")}
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
def add_line_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
|
500
|
+
if legend == :full
|
501
|
+
warn("Plotly backend does not support full verbosity legend")
|
502
|
+
end
|
503
|
+
|
504
|
+
legend_order = if variables.key?(:color)
|
505
|
+
if variables.key?(:style)
|
506
|
+
# both color and style
|
507
|
+
color_mapper.levels.product(style_mapper.levels)
|
508
|
+
else
|
509
|
+
# only color
|
510
|
+
color_mapper.levels
|
511
|
+
end
|
512
|
+
elsif variables.key?(:style)
|
513
|
+
# only style
|
514
|
+
style_mapper.levels
|
515
|
+
else
|
516
|
+
# no legend entries
|
517
|
+
nil
|
518
|
+
end
|
519
|
+
|
520
|
+
if legend_order
|
521
|
+
# sort traces
|
522
|
+
legend_index = legend_order.map.with_index { |name, i|
|
523
|
+
[Array(name).uniq.join(", "), i]
|
524
|
+
}.to_h
|
525
|
+
@traces = @traces.each_with_index.sort_by { |trace, trace_index|
|
526
|
+
index = legend_index.fetch(trace[:name], legend_order.length)
|
527
|
+
[index, trace_index]
|
528
|
+
}.map(&:first)
|
529
|
+
|
530
|
+
# remove duplicated legend entries
|
531
|
+
names = {}
|
532
|
+
@traces.each do |trace|
|
533
|
+
if trace[:showlegend] != false
|
534
|
+
name = trace[:name]
|
535
|
+
if name
|
536
|
+
if names.key?(name)
|
537
|
+
# Hide duplications
|
538
|
+
trace[:showlegend] = false
|
539
|
+
else
|
540
|
+
trace[:showlegend] = true
|
541
|
+
names[name] = true
|
542
|
+
end
|
543
|
+
else
|
544
|
+
# Hide no name trace in legend
|
545
|
+
trace[:showlegend] = false
|
546
|
+
end
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
private def convert_dash_pattern(pattern, line_width)
|
553
|
+
case pattern
|
554
|
+
when ""
|
555
|
+
:solid
|
556
|
+
else
|
557
|
+
pattern.map {|d| "#{line_width * d}px" }.join(",")
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
372
561
|
def set_xlabel(label)
|
373
562
|
@layout[:xaxis] ||= {}
|
374
563
|
@layout[:xaxis][:title] = label
|
@@ -303,7 +303,7 @@ module Charty
|
|
303
303
|
end
|
304
304
|
end
|
305
305
|
|
306
|
-
def scatter(x, y, variables,
|
306
|
+
def scatter(x, y, variables, color:, color_mapper:,
|
307
307
|
style:, style_mapper:, size:, size_mapper:)
|
308
308
|
kwd = {}
|
309
309
|
kwd[:edgecolor] = "w"
|
@@ -317,7 +317,7 @@ module Charty
|
|
317
317
|
end
|
318
318
|
|
319
319
|
unless size.nil?
|
320
|
-
size = size_mapper[size].map(
|
320
|
+
size = size_mapper[size].map {|x| scale_scatter_point_size(x).to_f }
|
321
321
|
points.set_sizes(size)
|
322
322
|
end
|
323
323
|
|
@@ -328,14 +328,15 @@ module Charty
|
|
328
328
|
|
329
329
|
sizes = points.get_sizes
|
330
330
|
points.set_linewidths(0.08 * Numpy.sqrt(Numpy.percentile(sizes, 10)))
|
331
|
+
end
|
331
332
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
333
|
+
def add_scatter_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
|
334
|
+
ax = @pyplot.gca
|
335
|
+
add_relational_plot_legend(
|
336
|
+
ax, variables, color_mapper, size_mapper, style_mapper,
|
337
|
+
legend, [:color, :s, :marker]
|
338
|
+
) do |label, kwargs|
|
339
|
+
ax.scatter([], [], label: label, **kwargs)
|
339
340
|
end
|
340
341
|
end
|
341
342
|
|
@@ -369,8 +370,8 @@ module Charty
|
|
369
370
|
|
370
371
|
RELATIONAL_PLOT_LEGEND_BRIEF_TICKS = 6
|
371
372
|
|
372
|
-
private def add_relational_plot_legend(ax,
|
373
|
-
legend_attributes, &func)
|
373
|
+
private def add_relational_plot_legend(ax, variables, color_mapper, size_mapper, style_mapper,
|
374
|
+
verbosity, legend_attributes, &func)
|
374
375
|
brief_ticks = RELATIONAL_PLOT_LEGEND_BRIEF_TICKS
|
375
376
|
verbosity = :auto if verbosity == true
|
376
377
|
|
@@ -391,24 +392,17 @@ module Charty
|
|
391
392
|
|
392
393
|
# color legend
|
393
394
|
|
394
|
-
brief_color =
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
false
|
400
|
-
else
|
401
|
-
color_mapper.levels.length > brief_ticks
|
402
|
-
end
|
403
|
-
else
|
404
|
-
false
|
405
|
-
end
|
395
|
+
brief_color = (color_mapper.map_type == :numeric) && (
|
396
|
+
(verbosity == :brief) || (
|
397
|
+
verbosity == :auto && color_mapper.levels.length > brief_ticks
|
398
|
+
)
|
399
|
+
)
|
406
400
|
case
|
407
401
|
when brief_color
|
408
402
|
# TODO: Also support LogLocator
|
409
403
|
# locator = Matplotlib.ticker.LogLocator.new(numticks: brief_ticks)
|
410
404
|
locator = Matplotlib.ticker.MaxNLocator.new(nbins: brief_ticks)
|
411
|
-
limits =
|
405
|
+
limits = color_mapper.levels.minmax
|
412
406
|
color_levels, color_formatted_levels = locator_to_legend_entries(locator, limits)
|
413
407
|
when color_mapper.levels.nil?
|
414
408
|
color_levels = color_formatted_levels = []
|
@@ -422,22 +416,14 @@ module Charty
|
|
422
416
|
|
423
417
|
color_levels.length.times do |i|
|
424
418
|
next if color_levels[i].nil?
|
425
|
-
color_value = color_mapper[color_levels[i]].to_hex_string
|
419
|
+
color_value = color_mapper[color_levels[i]].to_rgb.to_hex_string
|
426
420
|
update_legend.(variables[:color], color_formatted_levels[i], color: color_value)
|
427
421
|
end
|
428
422
|
|
429
|
-
brief_size =
|
430
|
-
|
431
|
-
size_mapper.
|
432
|
-
|
433
|
-
if size_mapper.levels.nil?
|
434
|
-
false
|
435
|
-
else
|
436
|
-
size_mapper.levels.length > brief_ticks
|
437
|
-
end
|
438
|
-
else
|
439
|
-
false
|
440
|
-
end
|
423
|
+
brief_size = (size_mapper.map_type == :numeric) && (
|
424
|
+
verbosity == :brief ||
|
425
|
+
(verbosity == :auto && size_mapper.levels.length > brief_ticks)
|
426
|
+
)
|
441
427
|
case
|
442
428
|
when brief_size
|
443
429
|
# TODO: Also support LogLocator
|
@@ -457,8 +443,9 @@ module Charty
|
|
457
443
|
|
458
444
|
size_levels.length.times do |i|
|
459
445
|
next if size_levels[i].nil?
|
460
|
-
|
461
|
-
|
446
|
+
line_width = scale_line_width(size_mapper[size_levels[i]])
|
447
|
+
point_size = scale_scatter_point_size(size_mapper[size_levels[i]])
|
448
|
+
update_legend.(variables[:size], size_formatted_levels[i], linewidth: line_width, s: point_size)
|
462
449
|
end
|
463
450
|
|
464
451
|
if legend_title.nil? && variables.key?(:style)
|
@@ -474,10 +461,12 @@ module Charty
|
|
474
461
|
else
|
475
462
|
""
|
476
463
|
end
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
464
|
+
dashes = if attrs.key?(:dashes)
|
465
|
+
attrs[:dashes]
|
466
|
+
else
|
467
|
+
""
|
468
|
+
end
|
469
|
+
update_legend.(variables[:style], level, marker: marker, dashes: dashes)
|
481
470
|
end
|
482
471
|
end
|
483
472
|
|
@@ -505,9 +494,96 @@ module Charty
|
|
505
494
|
min + x * (max - min)
|
506
495
|
end
|
507
496
|
|
497
|
+
def line(x, y, variables, color:, color_mapper:, size:, size_mapper:, style:, style_mapper:, ci_params:)
|
498
|
+
kws = {
|
499
|
+
markeredgewidth: 0.75,
|
500
|
+
markeredgecolor: "w",
|
501
|
+
}
|
502
|
+
ax = @pyplot.gca
|
503
|
+
|
504
|
+
x = x.to_a
|
505
|
+
y = y.to_a
|
506
|
+
lines = ax.plot(x, y, **kws)
|
507
|
+
|
508
|
+
lines.each do |line|
|
509
|
+
unless color.nil?
|
510
|
+
line.set_color(color_mapper[color].to_rgb.to_hex_string)
|
511
|
+
end
|
512
|
+
|
513
|
+
unless size.nil?
|
514
|
+
scaled_size = scale_line_width(size_mapper[size])
|
515
|
+
line.set_linewidth(scaled_size.to_f)
|
516
|
+
end
|
517
|
+
|
518
|
+
unless style.nil?
|
519
|
+
attributes = style_mapper[style]
|
520
|
+
if attributes.key?(:dashes)
|
521
|
+
line.set_dashes(attributes[:dashes])
|
522
|
+
end
|
523
|
+
if attributes.key?(:marker)
|
524
|
+
line.set_marker(PYPLOT_MARKERS[attributes[:marker]])
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
# TODO: support color, size, and style
|
530
|
+
|
531
|
+
line = lines[0]
|
532
|
+
line_color = line.get_color
|
533
|
+
line_alpha = line.get_alpha
|
534
|
+
line_capstyle = line.get_solid_capstyle
|
535
|
+
|
536
|
+
unless ci_params.nil?
|
537
|
+
y_min = ci_params[:y_min].to_a
|
538
|
+
y_max = ci_params[:y_max].to_a
|
539
|
+
case ci_params[:style]
|
540
|
+
when :band
|
541
|
+
# TODO: support to supply `alpha` via `err_kws`
|
542
|
+
ax.fill_between(x, y_min, y_max, color: line_color, alpha: 0.2)
|
543
|
+
when :bars
|
544
|
+
error_deltas = [
|
545
|
+
y.zip(y_min).map {|v, v_min| v - v_min },
|
546
|
+
y.zip(y_max).map {|v, v_max| v_max - v }
|
547
|
+
]
|
548
|
+
ebars = ax.errorbar(x, y, error_deltas,
|
549
|
+
linestyle: "", color: line_color, alpha: line_alpha)
|
550
|
+
ebars.get_children.each do |bar|
|
551
|
+
case bar
|
552
|
+
when Matplotlib.collections.LineCollection
|
553
|
+
bar.set_capstyle(line_capstyle)
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def add_line_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
|
561
|
+
ax = @pyplot.gca
|
562
|
+
add_relational_plot_legend(
|
563
|
+
ax, variables, color_mapper, size_mapper, style_mapper,
|
564
|
+
legend, [:color, :linewidth, :marker, :dashes]
|
565
|
+
) do |label, kwargs|
|
566
|
+
ax.plot([], [], label: label, **kwargs)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
|
571
|
+
private def scale_line_width(x)
|
572
|
+
min = 0.5 * @default_line_width
|
573
|
+
max = 2.0 * @default_line_width
|
574
|
+
|
575
|
+
min + x * (max - min)
|
576
|
+
end
|
577
|
+
|
508
578
|
private def locator_to_legend_entries(locator, limits)
|
509
579
|
vmin, vmax = limits
|
510
|
-
|
580
|
+
dtype = case vmin
|
581
|
+
when Numeric
|
582
|
+
:float64
|
583
|
+
else
|
584
|
+
:object
|
585
|
+
end
|
586
|
+
raw_levels = locator.tick_values(vmin, vmax).astype(dtype).to_a
|
511
587
|
raw_levels.reject! {|v| v < limits[0] || limits[1] < v }
|
512
588
|
|
513
589
|
formatter = case locator
|
@@ -596,6 +672,21 @@ module Charty
|
|
596
672
|
show
|
597
673
|
end
|
598
674
|
|
675
|
+
SAVEFIG_OPTIONAL_PARAMS = [
|
676
|
+
:dpi, :quality, :optimize, :progressive, :facecolor, :edgecolor,
|
677
|
+
:orientation, :papertype, :transparent, :bbox_inches, :pad_inches,
|
678
|
+
:bbox_extra_artists, :backend, :metadata, :pil_kwargs
|
679
|
+
].freeze
|
680
|
+
|
681
|
+
def save(filename, format: nil, title: nil, width: 700, height: 500, **kwargs)
|
682
|
+
params = {}
|
683
|
+
params[:format] = format unless format.nil?
|
684
|
+
SAVEFIG_OPTIONAL_PARAMS.each do |key|
|
685
|
+
params[key] = kwargs[key] if kwargs.key?(key)
|
686
|
+
end
|
687
|
+
@pyplot.savefig(filename, **params)
|
688
|
+
end
|
689
|
+
|
599
690
|
def show
|
600
691
|
@pyplot.show
|
601
692
|
end
|