Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support min: / max: options for y-axis range #67

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/squid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ module Interface
# @option settings [Numeric] :steps (4) the number of gridlines.
# @option settings [Boolean] :ticks (true) whether to plot the ticks.
# @option settings [Symbol] :type (:column) the type of graph.
# @option settings [Numeric] :min
# @option settings [Numeric] :max
def chart(data = {}, settings = {})
Graph.new(self, data, settings).draw
end
Expand Down
8 changes: 4 additions & 4 deletions lib/squid/axis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class Axis
include Format
attr_reader :data

def initialize(data, steps:, stack:, format:, &block)
@data, @steps, @stack, @format = data, steps, stack, format
def initialize(data, steps:, stack:, format:, min: nil, max: nil, &block)
@data, @steps, @stack, @format, @min, @max = data, steps, stack, format, min, max
@width_proc = block if block_given?
end

Expand Down Expand Up @@ -40,13 +40,13 @@ def label_width(label)

def min
if @data.any? && values.first && values.first.any?
[values.first.min, 0].min
@min || [values.first.min, 0].min
end
end

def max
if @data.any? && values.last && values.last.any?
closest_step_to values.last.max
closest_step_to(@max || values.last.max)
end
end

Expand Down
6 changes: 6 additions & 0 deletions lib/squid/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def self.integer
-> (value) { value.to_i }
end

def self.optional_integer
-> (value) { value && value.to_i }
end

def self.symbol
-> (value) { value.to_sym }
end
Expand All @@ -62,6 +66,8 @@ def self.array(proc = nil)
steps: {as: integer, default: '4'},
ticks: {as: boolean, default: 'true'},
type: {as: symbol, default: 'column'},
min: {as: optional_integer, default: nil},
max: {as: optional_integer, default: nil},
}

attr_accessor *ATTRIBUTES.keys
Expand Down
4 changes: 2 additions & 2 deletions lib/squid/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module Squid
class Graph
extend Settings
has_settings :baseline, :border, :chart, :colors, :every, :formats, :height
has_settings :legend, :line_widths, :steps, :ticks, :type, :labels
has_settings :legend, :line_widths, :steps, :ticks, :type, :labels, :min, :max

def initialize(document, data = {}, settings = {})
@data, @settings = data, settings
Expand Down Expand Up @@ -96,7 +96,7 @@ def right

def axis(first:, last:)
series = @data.values[first, last].map(&:values)
options = {steps: steps, stack: stack?, format: formats[first]}
options = {steps: steps, stack: stack?, format: formats[first], min: min, max: max}
Axis.new(series, options) {|label| @plot.width_of label}
end

Expand Down
11 changes: 8 additions & 3 deletions lib/squid/point.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ def self.for(series, minmax:, height:, labels:, stack:, formats:)
@max = Hash.new 0
min, max = minmax
offset = -> (value) { value * height.to_f / (max-min) }
y_offset = nil
series.map.with_index do |values, series_i|
values.map.with_index do |value, i|
h = y_for value, index: i, stack: false, &offset if value
y = y_for value, index: i, stack: stack, &offset if value
y = y - offset.call([min, 0].min) if value
if value
h = y_for value, index: i, stack: false, &offset
y = y_for value, index: i, stack: stack, &offset
y_offset ||= offset.call(min || 0) # only calculate this once, since the result will never change
y = y - y_offset
end

label = format_for value, formats[series_i] if labels[series_i]
new y: y, height: h, index: i, label: label, negative: value.to_f < 0
end
Expand Down
7 changes: 7 additions & 0 deletions spec/axis_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@
expect(labels).to eq %w(9.9 -5.1 -20 -35 -50)
end
end

describe 'given :min and :max' do
let(:options) { {steps: steps, stack: stack?, format: format, min: -500, max: 1000 } }
it "uses the give values as first and last label" do
expect(labels).to eq ["1,000", "625", "250", "-125", "-500"]
end
end
end

describe '#width' do
Expand Down
10 changes: 10 additions & 0 deletions spec/point_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,15 @@
expect(points.last.map &:y).to eq [nil, 89.95, 0.0]
end
end

context "given a positive min" do
let(:minmax) { [100, 150] }
let(:series) { [[110.0, 100, 130.0], [nil, 120.0, 150.0]] }

it 'generates y values relative to the minimum' do
expect(points.first.map &:y).to eq [20.0, 0.0, 60.0]
expect(points.last.map &:y).to eq [nil, 40.0, 100.0]
end
end
end
end
5 changes: 5 additions & 0 deletions spec/squid_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@
it { expect(colors_of(chart).fill_color).to eq [1.0, 0.0, 0.0] }
end

describe 'uses a given range with max and min options' do
let(:settings) { options.merge(steps: 5, max: 100, min: -100).except(:format) }
it { expect(strings_of chart).to eq ["100", "60", "20", "-20", "-60", "-100"] }
end

describe 'formats value labels with the value of the :format option' do
let(:settings) { options.merge label: true, format: :percentage }
it { expect(strings_of chart).to eq %w(50.0% -30.0% 20.0%) }
Expand Down