Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Josef Heinen 2020-03-29 10:45:41 +02:00
commit 1c66f4bf90
12 changed files with 119 additions and 34 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ deps/build.log
deps/deps.jl
Manifest.toml
dev/
test/tmpplotsave.hdf5

View File

@ -5,7 +5,7 @@ os:
# - osx
julia:
- 1
- 1.3
- 1.4
- nightly
matrix:
@ -32,7 +32,10 @@ before_install:
notifications:
email: true
after_success:
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi
- $TESTCMD -e 'using Pkg; Pkg.pin(PackageSpec(name="FixedPointNumbers", version="0.7")); Pkg.build(); Pkg.test(coverage=true)'
- $TESTCMD -e 'using Pkg; if VERSION == v"1.4"; Pkg.resolve(); end; Pkg.pin(PackageSpec(name="FixedPointNumbers", version="0.7")); Pkg.build(); Pkg.test(coverage=true)'

View File

@ -1,7 +1,7 @@
name = "Plots"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
author = ["Tom Breloff (@tbreloff)"]
version = "0.29.8"
version = "0.29.9"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

View File

@ -20,6 +20,7 @@
[![][pkgeval-img]][pkgeval-url]
[![][gitter-img]][gitter-url]
[![][docs-img]][docs-url]
[![Codecov](https://codecov.io/gh/JuliaPlots/Plots.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaPlots/Plots.jl)
#### Created by Tom Breloff (@tbreloff)

View File

@ -2,7 +2,7 @@ environment:
matrix:
# - julia_version: 0.7
- julia_version: 1
- julia_version: 1.3
- julia_version: 1.4
- julia_version: nightly
platform:
@ -33,10 +33,10 @@ install:
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
build_script:
- C:\julia\bin\julia --project=C:\projects\plots-jl -e "using Pkg; Pkg.pin(PackageSpec(name="""FixedPointNumbers""", version="""0.7"""))"
- C:\julia\bin\julia --project=C:\projects\plots-jl -e "using Pkg; if VERSION == v"""1.4"""; Pkg.resolve(); end; Pkg.pin(PackageSpec(name="""FixedPointNumbers""", version="""0.7"""))"
- echo "%JL_BUILD_SCRIPT%"
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
test_script:
- echo "%JL_TEST_SCRIPT%"
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"

10
codecov.yml Normal file
View File

@ -0,0 +1,10 @@
ignore:
- "src/backends/inspectdr.jl"
- "src/backends/orca.jl"
- "src/backends/pgfplots.jl"
- "src/backends/plotly.jl"
- "src/backends/plotlyjs.jl"
- "src/backends/pyplot.jl"
- "src/backends/web.jl"
- "src/fileio.jl"
- "src/ijulia.jl"

View File

@ -460,6 +460,29 @@ is_axis_attr_noletter(k) = haskey(_axis_defaults, k)
RecipesBase.is_key_supported(k::Symbol) = is_attr_supported(k)
const _internal_args =
[:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter]
const _magic_axis_args = [:axis, :tickfont, :guidefont]
const _magic_subplot_args = [:titlefont, :legendfont, :legendtitlefont, ]
const _magic_series_args = [:line, :marker, :fill]
function is_noletter_attribute(k)
is_axis_attr_noletter(k) && return true
k in _magic_axis_args && return true
return false
end
function is_default_attribute(k)
k in _internal_args && return true
k in _all_args && return true
is_axis_attr(k) && return true
is_noletter_attribute(k) && return true
k in _magic_subplot_args && return true
k in _magic_series_args && return true
Symbol(chop(string(k); head = 1, tail = 0)) in _magic_axis_args && return true
return false
end
# -----------------------------------------------------------------------------
makeplural(s::Symbol) = Symbol(string(s,"s"))
@ -1017,6 +1040,16 @@ function preprocessArgs!(plotattributes::AKW)
end
end
end
# handle axes guides
if haskey(plotattributes, :guide)
guide = pop!(plotattributes, :guide)
for letter in (:x, :y, :z)
guide_sym = Symbol(letter, :guide)
if !is_explicit(plotattributes, guide_sym)
plotattributes[guide_sym] = guide
end
end
end
# handle line args
for arg in wraptuple(pop_kw!(plotattributes, :line, ()))

View File

@ -1,4 +1,26 @@
# Error for aliases used in recipes
function warn_on_recipe_aliases!(plotattributes, recipe_type, args...)
for k in keys(plotattributes)
if !is_default_attribute(k)
dk = get(_keyAliases, k, k)
if k !== dk
@warn "Attribute alias `$k` detected in the $recipe_type recipe defined for the signature $(signature_string(Val{recipe_type}, args...)). To ensure expected behavior it is recommended to use the default attribute `$dk`."
end
plotattributes[dk] = pop_kw!(plotattributes, k)
end
end
end
warn_on_recipe_aliases!(v::AbstractVector, recipe_type, args) =
foreach(x -> warn_on_recipe_aliases!(x, recipe_type, args), v)
warn_on_recipe_aliases!(rd::RecipeData, recipe_type, args) =
warn_on_recipe_aliases!(rd.plotattributes, recipe_type, args)
function signature_string(::Type{Val{:user}}, args...)
return string("(::", join(string.(typeof.(args)), ", ::"), ")")
end
signature_string(::Type{Val{:type}}, T) = "(::Type{$T}, ::$T)"
signature_string(::Type{Val{:plot}}, st) = "(::Type{Val{:$st}}, ::AbstractPlot)"
signature_string(::Type{Val{:series}}, st) = "(::Type{Val{:$st}}, x, y, z)"
# ------------------------------------------------------------------
# preprocessing
@ -82,7 +104,11 @@ function _process_userrecipes(plt::Plot, plotattributes::AKW, args)
if isempty(next_series.args)
_process_userrecipe(plt, kw_list, next_series)
else
rd_list = RecipesBase.apply_recipe(next_series.plotattributes, next_series.args...)
rd_list = RecipesBase.apply_recipe(
next_series.plotattributes,
next_series.args...
)
warn_on_recipe_aliases!(rd_list, :user, next_series.args)
prepend!(still_to_process,rd_list)
end
end
@ -184,6 +210,7 @@ function _process_plotrecipe(plt::Plot, kw::AKW, kw_list::Vector{KW}, still_to_p
st = kw[:seriestype]
st = kw[:seriestype] = get(_typeAliases, st, st)
datalist = RecipesBase.apply_recipe(kw, Val{st}, plt)
warn_on_recipe_aliases!(datalist, :plot, st)
for data in datalist
preprocessArgs!(data.plotattributes)
if data.plotattributes[:seriestype] == st
@ -408,7 +435,9 @@ function _process_seriesrecipe(plt::Plot, plotattributes::AKW)
else
# get a sub list of series for this seriestype
datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, plotattributes[:x], plotattributes[:y], plotattributes[:z])
x, y, z = plotattributes[:x], plotattributes[:y], plotattributes[:z]
datalist = RecipesBase.apply_recipe(plotattributes, Val{st}, x, y, z)
warn_on_recipe_aliases!(datalist, :series, st)
# assuming there was no error, recursively apply the series recipes
for data in datalist

View File

@ -1261,8 +1261,8 @@ end
yflip := true
aspect_ratio := 1
rs, cs, zs = findnz(z.surf)
xlim := ignorenan_extrema(cs)
ylim := ignorenan_extrema(rs)
xlims := ignorenan_extrema(cs)
ylims := ignorenan_extrema(rs)
if plotattributes[:markershape] == :none
markershape := :circle
end

View File

@ -20,6 +20,7 @@ function prepareSeriesData(a::AbstractArray{<:MaybeNumber})
f = isimmutable(a) ? replace : replace!
a = f(x -> ismissing(x) || isinf(x) ? NaN : x, map(float, a))
end
prepareSeriesData(a::AbstractArray{<:Missing}) = fill(NaN, axes(a))
prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image
@ -171,9 +172,10 @@ end
@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
function _apply_type_recipe(plotattributes, v, letter)
_handle_axis_args!(plotattributes)
_preprocess_axis_args!(plotattributes, letter)
rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v)
_handle_axis_args!(plotattributes, letter)
warn_on_recipe_aliases!(plotattributes, :type, typeof(v))
_postprocess_axis_args!(plotattributes, letter)
return rdvec[1].args[1]
end
@ -181,15 +183,17 @@ end
# This sort of recipe should return a pair of functions... one to convert to number,
# and one to format tick values.
function _apply_type_recipe(plotattributes, v::AbstractArray, letter)
_handle_axis_args!(plotattributes)
_preprocess_axis_args!(plotattributes, letter)
# First we try to apply an array type recipe.
w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1]
warn_on_recipe_aliases!(plotattributes, :type, typeof(v))
# If the type did not change try it element-wise
if typeof(v) == typeof(w)
isempty(skipmissing(v)) && return Float64[]
x = first(skipmissing(v))
args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args
_handle_axis_args!(plotattributes, letter)
warn_on_recipe_aliases!(plotattributes, :type, typeof(x))
_postprocess_axis_args!(plotattributes, letter)
if length(args) == 2 && all(arg -> arg isa Function, args)
numfunc, formatter = args
return Formatted(map(numfunc, v), formatter)
@ -197,7 +201,7 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter)
return v
end
end
_handle_axis_args!(plotattributes, letter)
_postprocess_axis_args!(plotattributes, letter)
return w
end
@ -218,29 +222,32 @@ end
# end
# don't do anything for ints or floats
_apply_type_recipe(plotattributes, v::AbstractArray{T}, letter) where {T<:Union{Integer,AbstractFloat}} = v
_apply_type_recipe(plotattributes, v::AbstractArray{<:DataPoint}, letter) = v
# axis args in type recipes should only be applied to the current axis
function _handle_axis_args!(plotattributes, letter)
if letter in (:x, :y, :z)
replaceAliases!(plotattributes, _keyAliases)
for (k, v) in plotattributes
if haskey(_axis_defaults, k)
pop!(plotattributes, k)
lk = Symbol(letter, k)
# axis args before type recipes should still be mapped to all axes
function _preprocess_axis_args!(plotattributes)
for (k, v) in plotattributes
if is_noletter_attribute(k)
pop!(plotattributes, k)
for l in (:x, :y, :z)
lk = Symbol(l, k)
haskey(plotattributes, lk) || (plotattributes[lk] = v)
end
end
end
end
function _preprocess_axis_args!(plotattributes, letter)
plotattributes[:letter] = letter
_preprocess_axis_args!(plotattributes)
end
# axis args before type recipes should still be mapped to all axes
function _handle_axis_args!(plotattributes)
replaceAliases!(plotattributes, _keyAliases)
for (k, v) in plotattributes
if haskey(_axis_defaults, k)
pop!(plotattributes, k)
for letter in (:x, :y, :z)
# axis args in type recipes should only be applied to the current axis
function _postprocess_axis_args!(plotattributes, letter)
pop!(plotattributes, :letter)
if letter in (:x, :y, :z)
for (k, v) in plotattributes
if is_noletter_attribute(k)
pop!(plotattributes, k)
lk = Symbol(letter, k)
haskey(plotattributes, lk) || (plotattributes[lk] = v)
end

View File

@ -26,8 +26,9 @@ struct Attr <: AbstractDict{Symbol,Any}
defaults::KW
end
Base.getindex(attr::Attr, k) = haskey(attr.explicit,k) ?
attr.explicit[k] : attr.defaults[k]
function Base.getindex(attr::Attr, k)
return haskey(attr.explicit, k) ? attr.explicit[k] : attr.defaults[k]
end
Base.haskey(attr::Attr, k) = haskey(attr.explicit,k) || haskey(attr.defaults,k)
Base.get(attr::Attr, k, default) = haskey(attr, k) ? attr[k] : default
function Base.get!(attr::Attr, k, default)
@ -41,7 +42,7 @@ end
function Base.delete!(attr::Attr, k)
haskey(attr.explicit, k) && delete!(attr.explicit, k)
haskey(attr.defaults, k) && delete!(attr.defaults, k)
end
end
Base.length(attr::Attr) = length(union(keys(attr.explicit), keys(attr.defaults)))
function Base.iterate(attr::Attr)
exp_keys = keys(attr.explicit)