class Charty::Backends::Plotly

Constants

PLOTLY_HISTNORM

Attributes

chart_id[W]
plotly_src[W]
with_api_load_tag[W]
context[R]

Public Class Methods

chart_id() click to toggle source
# File lib/charty/backends/plotly.rb, line 19
def chart_id
  @chart_id ||= 0
end
ensure_playwright() click to toggle source
# File lib/charty/backends/plotly.rb, line 923
def self.ensure_playwright
  if @playwright_fiber.nil?
    begin
      require "playwright"
    rescue LoadError
      $stderr.puts "ERROR: You need to install playwright and playwright-ruby-client before using Plotly renderer"
      raise
    end

    @playwright_fiber = Fiber.new do
      playwright_cli_executable_path = ENV.fetch("PLAYWRIGHT_CLI_EXECUTABLE_PATH", "npx playwright")
      Playwright.create(playwright_cli_executable_path: playwright_cli_executable_path) do |playwright|
        playwright.chromium.launch(headless: true) do |browser|
          request = Fiber.yield
          loop do
            result = nil
            case request.shift
            when :finish
              break
            when :render
              input, output, format, element_id, width, height = request

              page = browser.new_page
              page.set_viewport_size(width: width, height: height)
              page.goto("file://#{input}")
              element = page.query_selector("\##{element_id}")

              kwargs = {type: format}
              kwargs[:path] = output unless output.nil?
              result = element.screenshot(**kwargs)
            end
            request = Fiber.yield(result)
          end
        end
      end
    end
    @playwright_fiber.resume
  end
end
notebook_renderer() click to toggle source

for new APIs

# File lib/charty/backends/plotly.rb, line 850
def self.notebook_renderer
  @notebook_renderer ||= PlotlyHelpers::NotebookRenderer.new
end
plotly_src() click to toggle source
# File lib/charty/backends/plotly.rb, line 29
def plotly_src
  @plotly_src ||= 'https://cdn.plot.ly/plotly-latest.min.js'
end
render_image(input, output, format, element_id, width, height) click to toggle source
# File lib/charty/backends/plotly.rb, line 971
def self.render_image(input, output, format, element_id, width, height)
  ensure_playwright if @playwright_fiber.nil?
  @playwright_fiber.resume([:render, input, output, format.to_s, element_id, width, height])
end
terminate_playwright() click to toggle source
# File lib/charty/backends/plotly.rb, line 963
def self.terminate_playwright
  return if @playwright_fiber.nil?

  @playwright_fiber.resume([:finish])
end
with_api_load_tag() click to toggle source
# File lib/charty/backends/plotly.rb, line 23
def with_api_load_tag
  return @with_api_load_tag unless @with_api_load_tag.nil?

  @with_api_load_tag = true
end

Public Instance Methods

add_line_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend) click to toggle source
# File lib/charty/backends/plotly.rb, line 501
def add_line_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
  if legend == :full
    warn("Plotly backend does not support full verbosity legend")
  end

  legend_order = if variables.key?(:color)
                   if variables.key?(:style)
                     # both color and style
                     color_mapper.levels.product(style_mapper.levels)
                   else
                     # only color
                     color_mapper.levels
                   end
                 elsif variables.key?(:style)
                   # only style
                   style_mapper.levels
                 else
                   # no legend entries
                   nil
                 end

  if legend_order
    # sort traces
    legend_index = legend_order.map.with_index { |name, i|
      [Array(name).uniq.join(", "), i]
    }.to_h
    @traces = @traces.each_with_index.sort_by { |trace, trace_index|
      index = legend_index.fetch(trace[:name], legend_order.length)
      [index, trace_index]
    }.map(&:first)

    # remove duplicated legend entries
    names = {}
    @traces.each do |trace|
      if trace[:showlegend] != false
        name = trace[:name]
        if name
          if names.key?(name)
            # Hide duplications
            trace[:showlegend] = false
          else
            trace[:showlegend] = true
            names[name] = true
          end
        else
          # Hide no name trace in legend
          trace[:showlegend] = false
        end
      end
    end
  end
end
add_scatter_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend) click to toggle source
# File lib/charty/backends/plotly.rb, line 365
def add_scatter_plot_legend(variables, color_mapper, size_mapper, style_mapper, legend)
  if legend == :full
    warn("Plotly backend does not support full verbosity legend")
  end
end
bar(bar_pos, group_names, values, colors, orient, label: nil, width: 0.8r, align: :center, conf_int: nil, error_colors: nil, error_width: nil, cap_size: nil) click to toggle source
# File lib/charty/backends/plotly.rb, line 129
def bar(bar_pos, group_names, values, colors, orient, label: nil, width: 0.8r,
        align: :center, conf_int: nil, error_colors: nil, error_width: nil, cap_size: nil)
  bar_pos = Array(bar_pos)
  values = Array(values)
  colors = Array(colors).map(&:to_hex_string)

  if orient == :v
    x, y = bar_pos, values
  else
    x, y = values, bar_pos
  end

  trace = {
    type: :bar,
    orientation: orient,
    x: x,
    y: y,
    width: width,
    marker: {color: colors}
  }
  trace[:name] = label unless label.nil?

  unless conf_int.nil?
    errors_low = conf_int.map.with_index {|(low, _), i| values[i] - low }
    errors_high = conf_int.map.with_index {|(_, high), i| high - values[i] }

    error_bar = {
      type: :data,
      visible: true,
      symmetric: false,
      array: errors_high,
      arrayminus: errors_low,
      color: error_colors[0].to_hex_string
    }
    error_bar[:thickness] = error_width unless error_width.nil?
    error_bar[:width] = cap_size unless cap_size.nil?

    error_bar_key = orient == :v ? :error_y : :error_x
    trace[error_bar_key] = error_bar
  end

  @traces << trace

  if group_names
    @layout[:barmode] = :group
  end
end
begin_figure() click to toggle source
# File lib/charty/backends/plotly.rb, line 124
def begin_figure
  @traces = []
  @layout = {showlegend: false}
end
box_plot(plot_data, group_names, orient:, colors:, gray:, dodge:, width: 0.8r, flier_size: 5, whisker: 1.5, notch: false) click to toggle source
# File lib/charty/backends/plotly.rb, line 177
def box_plot(plot_data, group_names,
             orient:, colors:, gray:, dodge:, width: 0.8r,
             flier_size: 5, whisker: 1.5, notch: false)
  colors = Array(colors).map(&:to_hex_string)
  gray = gray.to_hex_string
  width = Float(width)
  flier_size = Float(width)
  whisker = Float(whisker)

  traces = plot_data.map.with_index do |group_data, i|
    group_data = Array(group_data)
    trace = {
      type: :box,
      orientation: orient,
      name: group_names[i],
      marker: {color: colors[i]}
    }
    if orient == :v
      trace.update(y: group_data)
    else
      trace.update(x: group_data)
    end

    trace
  end

  traces.reverse! if orient == :h

  @traces.concat(traces)
end
disable_xaxis_grid() click to toggle source
# File lib/charty/backends/plotly.rb, line 686
def disable_xaxis_grid
  # do nothing
end
disable_yaxis_grid() click to toggle source
# File lib/charty/backends/plotly.rb, line 690
def disable_yaxis_grid
  # do nothing
end
grouped_box_plot(plot_data, group_names, color_names, orient:, colors:, gray:, dodge:, width: 0.8r, flier_size: 5, whisker: 1.5, notch: false) click to toggle source
# File lib/charty/backends/plotly.rb, line 208
def grouped_box_plot(plot_data, group_names, color_names,
                     orient:, colors:, gray:, dodge:, width: 0.8r,
                     flier_size: 5, whisker: 1.5, notch: false)
  colors = Array(colors).map(&:to_hex_string)
  gray = gray.to_hex_string
  width = Float(width)
  flier_size = Float(width)
  whisker = Float(whisker)

  @layout[:boxmode] = :group

  if orient == :h
    @layout[:xaxis] ||= {}
    @layout[:xaxis][:zeroline] = false

    plot_data = plot_data.map {|d| d.reverse }
    group_names = group_names.reverse
  end

  traces = color_names.map.with_index do |color_name, i|
    group_keys = group_names.flat_map.with_index { |name, j|
      Array.new(plot_data[i][j].length, name)
    }.flatten

    values = plot_data[i].flat_map {|d| Array(d) }

    trace = {
      type: :box,
      orientation: orient,
      name: color_name,
      marker: {color: colors[i]}
    }

    if orient == :v
      trace.update(y: values, x: group_keys.map(&:to_s))
    else
      trace.update(x: values, y: group_keys.map(&:to_s))
    end

    trace
  end

  @traces.concat(traces)
end
initilize() click to toggle source
# File lib/charty/backends/plotly.rb, line 34
def initilize
end
invert_yaxis() click to toggle source
# File lib/charty/backends/plotly.rb, line 694
def invert_yaxis
  @traces.each do |trace|
    case trace[:type]
    when :bar
      trace[:y].reverse!
    end
  end

  if @layout[:boxmode] == :group
    @traces.reverse!
  end

  if @layout[:yaxis] && @layout[:yaxis][:ticktext]
    @layout[:yaxis][:ticktext].reverse!
  end
end
label(x, y) click to toggle source
# File lib/charty/backends/plotly.rb, line 37
def label(x, y)
end
legend(loc:, title:) click to toggle source
# File lib/charty/backends/plotly.rb, line 711
def legend(loc:, title:)
  @layout[:showlegend] = true
  @layout[:legend] = {
    title: {
      text: title
    }
  }
  # TODO: Handle loc
end
line(x, y, variables, color:, color_mapper:, size:, size_mapper:, style:, style_mapper:, ci_params:) click to toggle source
# File lib/charty/backends/plotly.rb, line 378
def line(x, y, variables, color:, color_mapper:, size:, size_mapper:, style:, style_mapper:, ci_params:)
  x = case x
      when Charty::Vector
        x.to_a
      else
        orig_x, x = x, Array.try_convert(x)
        if x.nil?
          raise ArgumentError, "Invalid value for x: %p" % orig_x
        end
      end

  y = case y
      when Charty::Vector
        y.to_a
      else
        orig_y, y = y, Array.try_convert(y)
        if y.nil?
          raise ArgumentError, "Invalid value for y: %p" % orig_y
        end
      end

  name = []
  legend_title = []

  if color.nil?
    # TODO: do not hard code this
    line_color = Colors["#1f77b4"] # the first color of D3's category10 palette
  else
    line_color = color_mapper[color].to_rgb
    name << color
    legend_title << variables[:color]
  end

  unless style.nil?
    marker, dashes = style_mapper[style].values_at(:marker, :dashes)
    name << style
    legend_title << variables[:style]
  end

  trace = {
    type: :scatter,
    mode: marker.nil? ? "lines" : "lines+markers",
    x: x,
    y: y,
    line: {
      shape: :linear,
      color: line_color.to_hex_string
    }
  }

  default_line_width = 2.0
  unless size.nil?
    line_width = default_line_width + 2.0 * size_mapper[size]
    trace[:line][:width] = line_width
  end

  unless dashes.nil?
    trace[:line][:dash] = convert_dash_pattern(dashes, line_width || default_line_width)
  end

  unless marker.nil?
    trace[:marker] = {
      line: {
        width: 1,
        color: "#fff"
      },
      symbol: marker,
      size: 10
    }
  end

  unless ci_params.nil?
    case ci_params[:style]
    when :band
      y_min = ci_params[:y_min].to_a
      y_max = ci_params[:y_max].to_a
      @traces << {
        type: :scatter,
        x: x,
        y: y_max,
        mode: :lines,
        line: { shape: :linear, width: 0 },
        showlegend: false
      }
      @traces << {
        type: :scatter,
        x: x,
        y: y_min,
        mode: :lines,
        line: { shape: :linear, width: 0 },
        fill: :tonexty,
        fillcolor: line_color.to_rgba(alpha: 0.2).to_hex_string,
        showlegend: false
      }
    when :bars
      y_min = ci_params[:y_min].map.with_index {|v, i| y[i] - v }
      y_max = ci_params[:y_max].map.with_index {|v, i| v - y[i] }
      trace[:error_y] = {
        visible: true,
        type: :data,
        array: y_max,
        arrayminus: y_min
      }
      unless line_color.nil?
        trace[:error_y][:color] = line_color
      end
      unless line_width.nil?
        trace[:error_y][:thickness] = line_width
      end
    end
  end

  trace[:name] = name.uniq.join(", ") unless name.empty?

  @traces << trace

  unless legend_title.empty?
    @layout[:showlegend] = true
    @layout[:legend] ||= {}
    @layout[:legend][:title] = {text: legend_title.uniq.join(", ")}
  end
end
old_style_render(context, filename) click to toggle source
# File lib/charty/backends/plotly.rb, line 44
def old_style_render(context, filename)
  plot(nil, context)
end
plot(plot, context) click to toggle source
# File lib/charty/backends/plotly.rb, line 48
def plot(plot, context)
  context = context
  self.class.chart_id += 1

  case context.method
  when :bar
    render_graph(context, :bar)
  when :curve
    render_graph(context, :scatter)
  when :scatter
    render_graph(context, nil, options: {data: {mode: "markers"}})
  else
    raise NotImplementedError
  end
end
render(element_id: nil, format: nil, notebook: false) click to toggle source
# File lib/charty/backends/plotly.rb, line 781
def render(element_id: nil, format: nil, notebook: false)
  case format
  when :html, "html", nil
    format = "text/html"
  when :png, "png"
    format = "image/png"
  when :jpeg, "jpeg"
    format = "image/jpeg"
  end

  case format
  when "text/html"
    # render html after this case cause
  when "image/png", "image/jpeg"
    image_data = render_image(format, element_id: element_id, notebook: false)
    if notebook
      return [format, image_data]
    else
      return image_data
    end
  else
    raise ArgumentError,
          "Unsupported mime type to render: %p" % format
  end

  element_id = SecureRandom.uuid if element_id.nil?

  renderer = PlotlyHelpers::HtmlRenderer.new(full_html: !notebook)
  html = renderer.render({data: @traces, layout: @layout}, element_id: element_id)
  if notebook
    [format, html]
  else
    html
  end
end
render_mimebundle(include: [], exclude: []) click to toggle source
# File lib/charty/backends/plotly.rb, line 817
def render_mimebundle(include: [], exclude: [])
  types = case
         when IRubyHelper.vscode?,
           IRubyHelper.nteract?
           [:plotly_mimetype]
         else
           [:plotly_mimetype, :notebook]
         end
  bundle = Util.filter_map(types) { |type|
    case type
    when :plotly_mimetype
      render_plotly_mimetype_bundle
    when :notebook
      render_notebook_bundle
    end
  }.to_h
  bundle
end
save(filename, format: nil, title: nil, width: 700, height: 500, **kwargs) click to toggle source
# File lib/charty/backends/plotly.rb, line 721
def save(filename, format: nil, title: nil, width: 700, height: 500, **kwargs)
  format = detect_format(filename) if format.nil?

  case format
  when nil, :html, "text/html"
    save_html(filename, title: title, **kwargs)
  when :png, "png", "image/png",
       :jpeg, "jpeg", "image/jpeg"
    render_image(format, filename: filename, notebook: false, title: title, width: width, height: height, **kwargs)
  end
  nil
end
scatter(x, y, variables, color:, color_mapper:, style:, style_mapper:, size:, size_mapper:) click to toggle source
# File lib/charty/backends/plotly.rb, line 253
def scatter(x, y, variables, color:, color_mapper:,
            style:, style_mapper:, size:, size_mapper:)
  orig_x, orig_y = x, y

  x = case x
      when Charty::Vector
        x.to_a
      else
        Array.try_convert(x)
      end
  if x.nil?
    raise ArgumentError, "Invalid value for x: %p" % orig_x
  end

  y = case y
      when Charty::Vector
        y.to_a
      else
        Array.try_convert(y)
      end
  if y.nil?
    raise ArgumentError, "Invalid value for y: %p" % orig_y
  end

  unless color.nil? && style.nil?
    grouped_scatter(x, y, variables,
                    color: color, color_mapper: color_mapper,
                    style: style, style_mapper: style_mapper,
                    size: size, size_mapper: size_mapper)
    return
  end

  trace = {
    type: :scatter,
    mode: :markers,
    x: x,
    y: y,
    marker: {
      line: {
        width: 1,
        color: "#fff"
      },
      size: 10
    }
  }

  unless size.nil?
    trace[:marker][:size] = size_mapper[size].map {|x| 6.0 + x * 6.0 }
  end

  @traces << trace
end
series=(series) click to toggle source
# File lib/charty/backends/plotly.rb, line 40
def series=(series)
  @series = series
end
set_title(title) click to toggle source
# File lib/charty/backends/plotly.rb, line 614
def set_title(title)
  @layout[:title] ||= {}
  @layout[:title][:text] = title
end
set_xlabel(label) click to toggle source
# File lib/charty/backends/plotly.rb, line 619
def set_xlabel(label)
  @layout[:xaxis] ||= {}
  @layout[:xaxis][:title] = label
end
set_xlim(min, max) click to toggle source
# File lib/charty/backends/plotly.rb, line 653
def set_xlim(min, max)
  @layout[:xaxis] ||= {}
  @layout[:xaxis][:range] = [min, max]
end
set_xscale(scale) click to toggle source
# File lib/charty/backends/plotly.rb, line 663
def set_xscale(scale)
  scale = check_scale_type(scale, :xscale)
  @layout[:xaxis] ||= {}
  @layout[:xaxis][:type] = scale
end
set_xtick_labels(labels) click to toggle source
# File lib/charty/backends/plotly.rb, line 641
def set_xtick_labels(labels)
  @layout[:xaxis] ||= {}
  @layout[:xaxis][:tickmode] = "array"
  @layout[:xaxis][:ticktext] = labels
end
set_xticks(values) click to toggle source
# File lib/charty/backends/plotly.rb, line 629
def set_xticks(values)
  @layout[:xaxis] ||= {}
  @layout[:xaxis][:tickmode] = "array"
  @layout[:xaxis][:tickvals] = values
end
set_ylabel(label) click to toggle source
# File lib/charty/backends/plotly.rb, line 624
def set_ylabel(label)
  @layout[:yaxis] ||= {}
  @layout[:yaxis][:title] = label
end
set_ylim(min, max) click to toggle source
# File lib/charty/backends/plotly.rb, line 658
def set_ylim(min, max)
  @layout[:yaxis] ||= {}
  @layout[:yaxis][:range] = [min, max]
end
set_yscale(scale) click to toggle source
# File lib/charty/backends/plotly.rb, line 669
def set_yscale(scale)
  scale = check_scale_type(scale, :yscale)
  @layout[:yaxis] ||= {}
  @layout[:yaxis][:type] = scale
end
set_ytick_labels(labels) click to toggle source
# File lib/charty/backends/plotly.rb, line 647
def set_ytick_labels(labels)
  @layout[:yaxis] ||= {}
  @layout[:yaxis][:tickmode] = "array"
  @layout[:yaxis][:ticktext] = labels
end
set_yticks(values) click to toggle source
# File lib/charty/backends/plotly.rb, line 635
def set_yticks(values)
  @layout[:yaxis] ||= {}
  @layout[:yaxis][:tickmode] = "array"
  @layout[:yaxis][:tickvals] = values
end
univariate_histogram(hist, name, variable_name, stat, alpha, color, key_color, color_mapper, _multiple, _element, _fill, _shrink) click to toggle source
# File lib/charty/backends/plotly.rb, line 570
def univariate_histogram(hist, name, variable_name, stat,
                         alpha, color, key_color, color_mapper,
                         _multiple, _element, _fill, _shrink)
  value_axis = variable_name
  case value_axis
  when :x
    weights_axis = :y
    orientation = :v
  else
    weights_axis = :x
    orientation = :h
  end

  mid_points = hist.edges.each_cons(2).map {|a, b| a + (b - a) / 2 }

  trace = {
    type: :bar,
    name: name.to_s,
    value_axis => mid_points,
    weights_axis => hist.weights,
    orientation: orientation,
    opacity: alpha
  }

  if color.nil?
    trace[:marker] = {
      color: key_color.to_rgb.to_hex_string
    }
  else
    trace[:marker] = {
      color: color_mapper[color].to_rgb.to_hex_string
    }
  end

  @traces << trace

  @layout[:bargap] = 0.05

  if @traces.length > 1
    @layout[:barmode] = "overlay"
    @layout[:showlegend] = true
  end
end

Private Instance Methods

check_scale_type(val, name) click to toggle source
# File lib/charty/backends/plotly.rb, line 675
        def check_scale_type(val, name)
  case
  when :linear, :log
    val
  else
    raise ArgumentError,
          "Invalid #{name} type: %p" % val,
          caller
  end
end
convert_dash_pattern(pattern, line_width) click to toggle source
# File lib/charty/backends/plotly.rb, line 554
        def convert_dash_pattern(pattern, line_width)
  case pattern
  when ""
    :solid
  else
    pattern.map {|d| "#{line_width * d}px" }.join(",")
  end
end
default_html_title() click to toggle source
# File lib/charty/backends/plotly.rb, line 777
        def default_html_title
  "Charty plot"
end
detect_format(filename) click to toggle source
# File lib/charty/backends/plotly.rb, line 734
        def detect_format(filename)
  case File.extname(filename).downcase
  when ".htm", ".html"
    :html
  when ".png"
    :png
  when ".jpg", ".jpeg"
    :jpeg
  else
    raise ArgumentError,
          "Unable to infer file type from filename: %p" % filename
  end
end
div_id() click to toggle source
# File lib/charty/backends/plotly.rb, line 71
        def div_id
  "charty-plotly-#{self.class.chart_id}"
end
div_style() click to toggle source
# File lib/charty/backends/plotly.rb, line 75
        def div_style
  "width: 100%;height: 100%;"
end
grouped_scatter(x, y, variables, color:, color_mapper:, style:, style_mapper:, size:, size_mapper:) click to toggle source
# File lib/charty/backends/plotly.rb, line 306
        def grouped_scatter(x, y, variables, color:, color_mapper:,
                            style:, style_mapper:, size:, size_mapper:)
  @layout[:showlegend] = true

  groups = (0 ... x.length).group_by do |i|
    key = {}
    key[:color] = color[i] unless color.nil?
    key[:style] = style[i] unless style.nil?
    key
  end

  groups.each do |group_key, indices|
    trace = {
      type: :scatter,
      mode: :markers,
      x: x.values_at(*indices),
      y: y.values_at(*indices),
      marker: {
        line: {
          width: 1,
          color: "#fff"
        },
        size: 10
      }
    }

    unless size.nil?
      vals = size.values_at(*indices)
      trace[:marker][:size] = size_mapper[vals].map do |x|
        scale_scatter_point_size(x).to_f
      end
    end

    name = []
    legend_title = []

    if group_key.key?(:color)
      trace[:marker][:color] = color_mapper[group_key[:color]].to_hex_string
      name << group_key[:color]
      legend_title << variables[:color]
    end

    if group_key.key?(:style)
      trace[:marker][:symbol] = style_mapper[group_key[:style], :marker]
      name << group_key[:style]
      legend_title << variables[:style]
    end

    trace[:name] = name.uniq.join(", ") unless name.empty?

    @traces << trace

    unless legend_title.empty?
      @layout[:legend] ||= {}
      @layout[:legend][:title] = {text: legend_title.uniq.join(", ")}
    end
  end
end
plotly_load_tag() click to toggle source
# File lib/charty/backends/plotly.rb, line 64
        def plotly_load_tag
  if self.class.with_api_load_tag
    "<script type='text/javascript' src='#{self.class.plotly_src}'></script>"
  else
  end
end
render_graph(context, type, options: {}) click to toggle source
# File lib/charty/backends/plotly.rb, line 79
        def render_graph(context, type, options: {})
  data = context.series.map do |series|
    {
      type: type,
      x: series.xs.to_a,
      y: series.ys.to_a,
      name: series.label
    }.merge(options[:data] || {})
  end
  layout = {
    title: { text: context.title },
    xaxis: {
      title: context.xlabel,
      range: [context.range[:x].first, context.range[:x].last]
    },
    yaxis: {
      title: context.ylabel,
      range: [context.range[:y].first, context.range[:y].last]
    }
  }
  render_html(data, layout)
end
render_html(data, layout) click to toggle source
# File lib/charty/backends/plotly.rb, line 102
              def render_html(data, layout)
        <<~FRAGMENT
          #{plotly_load_tag unless self.class.chart_id > 1}
          <div id="#{div_id}" style="#{div_style}"></div>
          <script>
            Plotly.plot('#{div_id}', #{JSON.dump(data)}, #{JSON.dump(layout)} );
          </script>
        FRAGMENT
      end
render_image(format=nil, filename: nil, element_id: nil, notebook: false, title: nil, width: nil, height: nil) click to toggle source
# File lib/charty/backends/plotly.rb, line 854
        def render_image(format=nil, filename: nil, element_id: nil, notebook: false,
                 title: nil, width: nil, height: nil)
  format = "image/png" if format.nil?
  case format
  when :png, "png", :jpeg, "jpeg"
    image_type = format.to_s
  when "image/png", "image/jpeg"
    image_type = format.split("/").last
  else
    raise ArgumentError,
          "Unsupported mime type to render image: %p" % format
  end

  height = 525 if height.nil?
  width = (height * Math.sqrt(2)).to_i if width.nil?
  title = "Charty plot" if title.nil?

  element_id = SecureRandom.uuid if element_id.nil?
  element_id = "charty-plotly-#{element_id}"
  Dir.mktmpdir do |tmpdir|
    html_filename = File.join(tmpdir, "%s.html" % element_id)
    save_html(html_filename, title: title, element_id: element_id)
    return self.class.render_image(html_filename, filename, image_type, element_id, width, height)
  end
end
render_notebook_bundle() click to toggle source
# File lib/charty/backends/plotly.rb, line 842
        def render_notebook_bundle
  renderer = self.class.notebook_renderer
  renderer.activate
  html = renderer.render({data: @traces, layout: @layout})
  [ "text/html", html ]
end
render_plotly_mimetype_bundle() click to toggle source
# File lib/charty/backends/plotly.rb, line 836
        def render_plotly_mimetype_bundle
  renderer = PlotlyHelpers::PlotlyRenderer.new
  obj = renderer.render({data: @traces, layout: @layout})
  [ "application/vnd.plotly.v1+json", obj ]
end
save_html(filename, title:, element_id: nil) click to toggle source
# File lib/charty/backends/plotly.rb, line 748
              def save_html(filename, title:, element_id: nil)
        html = <<~HTML
          <!DOCTYPE html>
          <html>
          <head>
          <meta charset="utf-8">
          <title>%{title}</title>
          <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
          </head>
          <body>
          <div id="%{id}" style="width: 100%%; height:100%%;"></div>
          <script type="text/javascript">
          Plotly.newPlot("%{id}", %{data}, %{layout});
          </script>
          </body>
          </html>
        HTML

        element_id = SecureRandom.uuid if element_id.nil?

        html %= {
          title: title || default_html_title,
          id: element_id,
          data: JSON.dump(@traces),
          layout: JSON.dump(@layout)
        }
        File.write(filename, html)
      end
scale_scatter_point_size(x) click to toggle source
# File lib/charty/backends/plotly.rb, line 371
        def scale_scatter_point_size(x)
  min = 6
  max = 12

  min + x * (max - min)
end