diff --git a/src/recipes.jl b/src/recipes.jl index 37210363..ef37f184 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -323,7 +323,7 @@ end # create a bar plot as a filled step function @recipe function f(::Type{Val{:bar}}, x, y, z) - procx, procy, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y) nx, ny = length(procx), length(procy) axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis] cv = [discrete_value!(axis, xi)[1] for xi=procx] @@ -380,6 +380,7 @@ end x := xseg.pts y := yseg.pts seriestype := :shape + ylims --> wautolims () end @deps bar shape @@ -402,39 +403,64 @@ function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, end end -function _hist_ylim_lo{T<:Real}(ymin::T, yscale::Symbol) - if (yscale in _logScales) - ymin / T(_logScaleBases[yscale]^log10(2)) + +function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol) + if (scale in _logScales) + !isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3) else zero(T) end end -function _hist_ylim_hi{T<:Real}(ymax::T, yscale::Symbol) - if (yscale in _logScales) - ymax * T(_logScaleBases[yscale]^log10(2)) +function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol) + lo = if (scale in _logScales) + _binbarlike_baseline(min_value, scale) else - ymax * T(1.1) - end + min(min_value * T(1.1), zero(T)) + end::T + + hi = if !isnan(max_value) + if (scale in _logScales) + max_value * T(_logScaleBases[scale]^log10(2)) + else + max(max_value * T(1.1), zero(T)) + end + else + one(T) + end::T + + (lo, hi) end +function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol) + w_adj = _scale_adjusted_values(T, w, wscale) + w_min = minimum(w_adj) + w_max = maximum(w_adj) + baseline = _binbarlike_baseline(w_min, wscale) + autolims = _binbarlike_autolims(w_min, w_max,wscale) + w_adj, baseline, autolims +end + +function _preprocess_barlike(d, x, y) + xscale = get(d, :xscale, :identity) + yscale = get(d, :yscale, :identity) + weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale) + x, weights, xscale, yscale, baseline, wautolims +end + function _preprocess_binlike(d, x, y) xscale = get(d, :xscale, :identity) yscale = get(d, :yscale, :identity) - T = float(promote_type(eltype(x), eltype(y))) - edge = map(T, x) - weights = _scale_adjusted_values(T, y, yscale) - w_min = minimum(weights) - baseline = _hist_ylim_lo(isnan(w_min) ? one(T) : w_min, yscale) - edge, weights, xscale, yscale, baseline + edge = T.(x) + weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale) + edge, weights, xscale, yscale, baseline, wautolims end - @recipe function f(::Type{Val{:barbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) if (d[:bar_width] == nothing) bar_width := diff(edge) end @@ -447,7 +473,7 @@ end @recipe function f(::Type{Val{:scatterbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) xerror := diff(edge)/2 x := _bin_centers(edge) y := weights @@ -512,7 +538,7 @@ end @recipe function f(::Type{Val{:stepbins}}, x, y, z) axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis] - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) if !isvertical(d) @@ -539,7 +565,7 @@ end y := ypts seriestype := :path - ylims --> [baseline, _hist_ylim_hi(maximum(weights), yscale)] + ylims --> wautolims () end Plots.@deps stepbins path @@ -639,7 +665,7 @@ end if d[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights) xerror --> diff(h.edges[1])/2 seriestype := :scatter (Plots._bin_centers(edge), weights)