Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1c66f4bf90
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ deps/build.log
|
|||||||
deps/deps.jl
|
deps/deps.jl
|
||||||
Manifest.toml
|
Manifest.toml
|
||||||
dev/
|
dev/
|
||||||
|
test/tmpplotsave.hdf5
|
||||||
|
|||||||
@ -5,7 +5,7 @@ os:
|
|||||||
# - osx
|
# - osx
|
||||||
julia:
|
julia:
|
||||||
- 1
|
- 1
|
||||||
- 1.3
|
- 1.4
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
@ -32,7 +32,10 @@ before_install:
|
|||||||
notifications:
|
notifications:
|
||||||
email: true
|
email: true
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
|
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
|
||||||
- if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; 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)'
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
name = "Plots"
|
name = "Plots"
|
||||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||||
author = ["Tom Breloff (@tbreloff)"]
|
author = ["Tom Breloff (@tbreloff)"]
|
||||||
version = "0.29.8"
|
version = "0.29.9"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
[![][pkgeval-img]][pkgeval-url]
|
[![][pkgeval-img]][pkgeval-url]
|
||||||
[![][gitter-img]][gitter-url]
|
[![][gitter-img]][gitter-url]
|
||||||
[![][docs-img]][docs-url]
|
[![][docs-img]][docs-url]
|
||||||
|
[](https://codecov.io/gh/JuliaPlots/Plots.jl)
|
||||||
|
|
||||||
#### Created by Tom Breloff (@tbreloff)
|
#### Created by Tom Breloff (@tbreloff)
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ environment:
|
|||||||
matrix:
|
matrix:
|
||||||
# - julia_version: 0.7
|
# - julia_version: 0.7
|
||||||
- julia_version: 1
|
- julia_version: 1
|
||||||
- julia_version: 1.3
|
- julia_version: 1.4
|
||||||
- julia_version: nightly
|
- julia_version: nightly
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
@ -33,7 +33,7 @@ install:
|
|||||||
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
|
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
|
||||||
|
|
||||||
build_script:
|
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%"
|
- echo "%JL_BUILD_SCRIPT%"
|
||||||
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
|
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
|
||||||
|
|
||||||
|
|||||||
10
codecov.yml
Normal file
10
codecov.yml
Normal 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"
|
||||||
33
src/args.jl
33
src/args.jl
@ -460,6 +460,29 @@ is_axis_attr_noletter(k) = haskey(_axis_defaults, k)
|
|||||||
|
|
||||||
RecipesBase.is_key_supported(k::Symbol) = is_attr_supported(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"))
|
makeplural(s::Symbol) = Symbol(string(s,"s"))
|
||||||
@ -1017,6 +1040,16 @@ function preprocessArgs!(plotattributes::AKW)
|
|||||||
end
|
end
|
||||||
end
|
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
|
# handle line args
|
||||||
for arg in wraptuple(pop_kw!(plotattributes, :line, ()))
|
for arg in wraptuple(pop_kw!(plotattributes, :line, ()))
|
||||||
|
|||||||
@ -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
|
# preprocessing
|
||||||
@ -82,7 +104,11 @@ function _process_userrecipes(plt::Plot, plotattributes::AKW, args)
|
|||||||
if isempty(next_series.args)
|
if isempty(next_series.args)
|
||||||
_process_userrecipe(plt, kw_list, next_series)
|
_process_userrecipe(plt, kw_list, next_series)
|
||||||
else
|
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)
|
prepend!(still_to_process,rd_list)
|
||||||
end
|
end
|
||||||
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]
|
||||||
st = kw[:seriestype] = get(_typeAliases, st, st)
|
st = kw[:seriestype] = get(_typeAliases, st, st)
|
||||||
datalist = RecipesBase.apply_recipe(kw, Val{st}, plt)
|
datalist = RecipesBase.apply_recipe(kw, Val{st}, plt)
|
||||||
|
warn_on_recipe_aliases!(datalist, :plot, st)
|
||||||
for data in datalist
|
for data in datalist
|
||||||
preprocessArgs!(data.plotattributes)
|
preprocessArgs!(data.plotattributes)
|
||||||
if data.plotattributes[:seriestype] == st
|
if data.plotattributes[:seriestype] == st
|
||||||
@ -408,7 +435,9 @@ function _process_seriesrecipe(plt::Plot, plotattributes::AKW)
|
|||||||
|
|
||||||
else
|
else
|
||||||
# get a sub list of series for this seriestype
|
# 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
|
# assuming there was no error, recursively apply the series recipes
|
||||||
for data in datalist
|
for data in datalist
|
||||||
|
|||||||
@ -1261,8 +1261,8 @@ end
|
|||||||
yflip := true
|
yflip := true
|
||||||
aspect_ratio := 1
|
aspect_ratio := 1
|
||||||
rs, cs, zs = findnz(z.surf)
|
rs, cs, zs = findnz(z.surf)
|
||||||
xlim := ignorenan_extrema(cs)
|
xlims := ignorenan_extrema(cs)
|
||||||
ylim := ignorenan_extrema(rs)
|
ylims := ignorenan_extrema(rs)
|
||||||
if plotattributes[:markershape] == :none
|
if plotattributes[:markershape] == :none
|
||||||
markershape := :circle
|
markershape := :circle
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,6 +20,7 @@ function prepareSeriesData(a::AbstractArray{<:MaybeNumber})
|
|||||||
f = isimmutable(a) ? replace : replace!
|
f = isimmutable(a) ? replace : replace!
|
||||||
a = f(x -> ismissing(x) || isinf(x) ? NaN : x, map(float, a))
|
a = f(x -> ismissing(x) || isinf(x) ? NaN : x, map(float, a))
|
||||||
end
|
end
|
||||||
|
prepareSeriesData(a::AbstractArray{<:Missing}) = fill(NaN, axes(a))
|
||||||
prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
|
prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a)
|
||||||
prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
|
prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf))
|
||||||
prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image
|
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.")
|
@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)
|
function _apply_type_recipe(plotattributes, v, letter)
|
||||||
_handle_axis_args!(plotattributes)
|
_preprocess_axis_args!(plotattributes, letter)
|
||||||
rdvec = RecipesBase.apply_recipe(plotattributes, typeof(v), v)
|
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]
|
return rdvec[1].args[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -181,15 +183,17 @@ end
|
|||||||
# This sort of recipe should return a pair of functions... one to convert to number,
|
# This sort of recipe should return a pair of functions... one to convert to number,
|
||||||
# and one to format tick values.
|
# and one to format tick values.
|
||||||
function _apply_type_recipe(plotattributes, v::AbstractArray, letter)
|
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.
|
# First we try to apply an array type recipe.
|
||||||
w = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1]
|
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 the type did not change try it element-wise
|
||||||
if typeof(v) == typeof(w)
|
if typeof(v) == typeof(w)
|
||||||
isempty(skipmissing(v)) && return Float64[]
|
isempty(skipmissing(v)) && return Float64[]
|
||||||
x = first(skipmissing(v))
|
x = first(skipmissing(v))
|
||||||
args = RecipesBase.apply_recipe(plotattributes, typeof(x), x)[1].args
|
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)
|
if length(args) == 2 && all(arg -> arg isa Function, args)
|
||||||
numfunc, formatter = args
|
numfunc, formatter = args
|
||||||
return Formatted(map(numfunc, v), formatter)
|
return Formatted(map(numfunc, v), formatter)
|
||||||
@ -197,7 +201,7 @@ function _apply_type_recipe(plotattributes, v::AbstractArray, letter)
|
|||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
_handle_axis_args!(plotattributes, letter)
|
_postprocess_axis_args!(plotattributes, letter)
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -218,29 +222,32 @@ end
|
|||||||
# end
|
# end
|
||||||
|
|
||||||
# don't do anything for ints or floats
|
# 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
|
# axis args before type recipes should still be mapped to all axes
|
||||||
function _handle_axis_args!(plotattributes, letter)
|
function _preprocess_axis_args!(plotattributes)
|
||||||
if letter in (:x, :y, :z)
|
for (k, v) in plotattributes
|
||||||
replaceAliases!(plotattributes, _keyAliases)
|
if is_noletter_attribute(k)
|
||||||
for (k, v) in plotattributes
|
pop!(plotattributes, k)
|
||||||
if haskey(_axis_defaults, k)
|
for l in (:x, :y, :z)
|
||||||
pop!(plotattributes, k)
|
lk = Symbol(l, k)
|
||||||
lk = Symbol(letter, k)
|
|
||||||
haskey(plotattributes, lk) || (plotattributes[lk] = v)
|
haskey(plotattributes, lk) || (plotattributes[lk] = v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
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
|
# axis args in type recipes should only be applied to the current axis
|
||||||
function _handle_axis_args!(plotattributes)
|
function _postprocess_axis_args!(plotattributes, letter)
|
||||||
replaceAliases!(plotattributes, _keyAliases)
|
pop!(plotattributes, :letter)
|
||||||
for (k, v) in plotattributes
|
if letter in (:x, :y, :z)
|
||||||
if haskey(_axis_defaults, k)
|
for (k, v) in plotattributes
|
||||||
pop!(plotattributes, k)
|
if is_noletter_attribute(k)
|
||||||
for letter in (:x, :y, :z)
|
pop!(plotattributes, k)
|
||||||
lk = Symbol(letter, k)
|
lk = Symbol(letter, k)
|
||||||
haskey(plotattributes, lk) || (plotattributes[lk] = v)
|
haskey(plotattributes, lk) || (plotattributes[lk] = v)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -26,8 +26,9 @@ struct Attr <: AbstractDict{Symbol,Any}
|
|||||||
defaults::KW
|
defaults::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
Base.getindex(attr::Attr, k) = haskey(attr.explicit,k) ?
|
function Base.getindex(attr::Attr, k)
|
||||||
attr.explicit[k] : attr.defaults[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.haskey(attr::Attr, k) = haskey(attr.explicit,k) || haskey(attr.defaults,k)
|
||||||
Base.get(attr::Attr, k, default) = haskey(attr, k) ? attr[k] : default
|
Base.get(attr::Attr, k, default) = haskey(attr, k) ? attr[k] : default
|
||||||
function Base.get!(attr::Attr, k, default)
|
function Base.get!(attr::Attr, k, default)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user