Class: RVGP::Plot::Gnuplot::ColumnAndLineChart

Inherits:
ChartBuilder
  • Object
show all
Defined in:
lib/rvgp/plot/gnuplot.rb

Overview

This Chart element contains the logic used to render histograms (bars) along with lines, onto the plot canvas

Constant Summary

Constants inherited from ChartBuilder

RVGP::Plot::Gnuplot::ChartBuilder::ONE_MONTH_IN_SECONDS

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts, gnuplot) ⇒ ColumnAndLineChart

Create a chart

Parameters:

Options Hash (opts):

  • :domain (Symbol)

    This option specifies the ‘type’ of the domain. Currently, the only supported type is :monthly

  • :xrange_start (Integer, Date)

    The plot domain origin, either the number 1, or a date

  • :xrange_end (Date)

    The end of the plot domain

  • :axis (Hash<Symbol, String>)

    Axis labels. At the moment, :bottom and :left are supported keys.

  • :is_clustered (TrueClass, FalseClass) — default: false

    A flag indicating whether to cluster (true) or row-stack (false) the bar series.

  • :columns_rendered_as (Symbol)

    There are two methods that can be used to render columns (:histograms & :boxes). The :boxes method supports time-format domains. While :histograms supports non-reversed series ranges.

  • :series_types (Hash<String, Symbol>)

    A hash, indexed by series name, whose value is either :column, or :line.



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/rvgp/plot/gnuplot.rb', line 213

def initialize(opts, gnuplot)
  super opts, gnuplot
  @is_clustered = opts[:is_clustered]
  @columns_rendered_as = opts[:columns_rendered_as]
  @columns_rendered_as ||= @domain == :monthly ? :boxes : :histograms

  @series_types = {}
  @series_types = opts[:series_types].transform_keys(&:to_s) if opts[:series_types]

  case @columns_rendered_as
  when :histograms
    gnuplot.set 'style', format('histogram %s', clustered? ? 'clustered' : 'rowstacked')
    gnuplot.set 'style', 'fill solid'
  when :boxes
    @reverse_series_range = true
    # This puts a black line around the columns:
    gnuplot.set 'style', 'fill solid border -1'
    reverse_series_colors!

    # TODO: The box width straddles the tic, which, causes the box widths to
    # be half-width on the left and right sides of the plot. Roughly here,
    # we want to expand that xrange start/end by maybe two weeks.
    # This will require a bit more work than we want atm, because:
    # 1. We'd have to change the timefmt, and the grids, to report days
    # 2. We need to move the gnuplot.set in the initializer() into something
    #    farther down the code path.
  else
    raise StandardError, format('Unsupported columns_rendered_as %s', @columns_rendered_as.inspect)
  end
end

Class Method Details

.typesArray<String>

The chart types we support, intended for use in the chart_type parameter of your plot yaml. This class supports: COMBO column_and_lines column lines.

Returns:

  • (Array<String>)

    Supported chart types.



297
298
299
# File 'lib/rvgp/plot/gnuplot.rb', line 297

def self.types
  %w[COMBO column_and_lines column lines]
end

Instance Method Details

#clustered?TrueClass, FalseClass

Returns the value of the :is_clusted initialization parameter.

Returns:

  • (TrueClass, FalseClass)

    Whether or not this chart is clustered



246
247
248
# File 'lib/rvgp/plot/gnuplot.rb', line 246

def clustered?
  @is_clustered
end

#format_num(num) ⇒ String

Returns the column number specifier, a string, for use by Plot#plot_command, when building charts. In some charts, this is as simple as num + 1. In others, this line can contain more complex gnuplot code.

Returns:

  • (String)

    Returns the gnuplot formatted series_num, for the series at position num.



282
283
284
285
286
287
288
289
290
291
292
# File 'lib/rvgp/plot/gnuplot.rb', line 282

def format_num(num)
  if reverse_series_range? && series_type(num) == :column
    columns_for_sum = num.downto(1).map do |n|
      # We need to handle empty numbers, in order to fix that weird double-wide column bug
      format '(valid(%<num>s) ? column(%<num>s) : 0.0)', num: n + 1 if series_type(n) == :column
    end
    format '(%s)', columns_for_sum.compact.join('+')
  else
    super(num)
  end
end

#series(num) ⇒ Hash<Symbol, Object>

The gnuplot data specifier components, for series n

Parameters:

  • num (Integer)

    Series number

Returns:

  • (Hash<Symbol, Object>)

    :using and :with strings, for use by gnuplot



253
254
255
256
257
258
259
260
# File 'lib/rvgp/plot/gnuplot.rb', line 253

def series(num)
  type = series_type num
  using = [using(type)]

  using.send(*@columns_rendered_as == :histograms ? [:push, 'xtic(1)'] : [:unshift, '1'])

  { using: using, with: with(type) }
end

#series_range(num_cols) ⇒ Enumerator

Returns a enumerator, for use by Plot#plot_command, when building charts. Mostly, this method is what determines if the series are started from one, going up to numcols. Or, are started from num_cols, and go down to one.

Returns:

  • (Enumerator)

    An enumerator to progress through the chart’s series



271
272
273
274
275
276
277
278
279
# File 'lib/rvgp/plot/gnuplot.rb', line 271

def series_range(num_cols)
  ret = super num_cols
  return ret unless @columns_rendered_as == :boxes

  # We want the lines to draw over the columns. This achieves that.
  # It's possible that you want lines behind the columns. If so, add
  # an option to the class and submit a pr..
  ret.sort_by { |n| series_type(n) == :column ? 0 : 1 }
end

#series_type(num) ⇒ Symbol

Given the provided column number, return either :column, or :line, depending on whether this column has a value, as specified in the initialization parameter :series_types

Returns:

  • (Symbol)

    Either :column, or :line



265
266
267
268
# File 'lib/rvgp/plot/gnuplot.rb', line 265

def series_type(num)
  title = @gnuplot.series_name(num)
  @series_types.key?(title) ? @series_types[title].downcase.to_sym : :column
end