module Nyaplot # Jsonizable Object to which diagrams are registered # Properties of Nyaplot::Plot are embeded into the JSON object as a part of property 'panes' by Nyaplot::Frame class Plot include Jsonizable # @!attribute width # @return [Numeric] the width # @!attribute height # @return [Numeric] the height # @!attribute margin # @return [Hash] the margin # @!attribute xrange # @return [Array, Array, Array] the name of width set # @!attribute yrange # @return [Array, Array, Array] the name of width set # @!attribute x_label # @return [String] the name of label placed along x-axis # @!attribute y_label # @return [String] the name of label placed along y-axis # @!attribute bg_color # @return [String] the code of color which background is filled in # @!attribute grid_color # @return [String] the code of color which grid lines are filled in # @!attribute legend # @return [Boolean] whether to show legend or not # @!attribute legend_width # @return [Numeric] the width of legend area # @!attribute legend_options # @return [Hash] the name of width set # @!attribute zoom # @return [Boolean] whether to enable zooming # @!attribute rotate_x_label # @return [Numeric] the angle to rotate x label (radian) # @!attribute rotate_y_label # @return [Numeric] the angle to rotate y label (radian) # @!attribute x_scale # @return [String] the type of scale ("linear", "log" and "pow" are supported.) # @!attribute y_scale # @return [String] the type of scale ("linear", "log" and "pow" are supported.) define_properties(:diagrams, :filter) define_group_properties(:options, [:width, :height, :margin, :xrange, :yrange, :x_label, :y_label, :bg_color, :grid_color, :legend, :legend_width, :legend_options, :zoom, :rotate_x_label, :rotate_y_label, :x_scale, :y_scale]) def initialize(&block) init_properties set_property(:diagrams, []) set_property(:options, {}) set_property(:width, nil) set_property(:legend, nil) set_property(:zoom, nil) yield if block_given? end # Add diagram with Array # @param [Symbol] type the type of diagram to add # @param [Array] *data array from which diagram is created # @example # plot.add(:scatter, [0,1,2], [0,1,2]) def add(type, *data) labels = data.map.with_index{|d, i| 'data' + i.to_s} raw_data = data.each.with_index.reduce({}){|memo, (d, i)| memo[labels[i]]=d; next memo} df = DataFrame.new(raw_data) return add_with_df(df, type, *labels) end # Add diagram with DataFrame # @param [DataFrame] DataFrame from which diagram is created # @param [Symbol] type the type of diagram to add # @param [Array] *labels column labels for x, y or some other dimension # @example # df = Nyaplot::DataFrame.new({x: [0,1,2], y: [0,1,2]}) # plot.add(df, :scatter, :x, :y) def add_with_df(df, type, *labels) diagram = Diagram.new(df, type, labels) diagrams = get_property(:diagrams) diagrams.push(diagram) return diagram end # Show plot automatically on IRuby notebook def to_iruby Frame.new.tap {|f| f.add(self) }.to_iruby end # Show plot on IRuby notebook def show Frame.new.tap {|f| f.add(self) }.show end # export html file def export_html(path=nil) require 'securerandom' path = "./plot-" + SecureRandom.uuid().to_s + ".html" if path.nil? Frame.new.tap {|f| f.add(self) }.export_html(path) end # @return [Array] names of dataframe used by diagrams belog to this plot def df_list arr=[] diagrams = get_property(:diagrams) diagrams.each{|d| arr.push(d.df_name)} return arr end def before_to_json diagrams = get_property(:diagrams) return if diagrams.length == 0 # set default values when not specified by users zoom(true) if zoom.nil? && diagrams.all?{|d| d.zoom?} if width.nil? if legend == true width(800) else width(700) end end [:xrange, :yrange].each do |symbol| if get_property(:options)[symbol].nil? range = [] diagrams.each{|diagram| range.push(diagram.send(symbol))} if range.all? {|r| r.length == 2} # continuous data range = range.transpose range = [range[0].min, range[1].max] self.send(symbol, range) else # discrete data range.flatten!.uniq! self.send(symbol, range) end end end end # Shortcut method to configure plot # @example # plot = Nyaplot::Plot.new # plot.configure do # width(700) # height(700) # end def configure(&block) self.instance_eval(&block) if block_given? end end end