Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0485b1313a | |||
| f0f28086a9 | |||
| 580ac8a9d1 | |||
| 84fc6b0be0 | |||
| de81220c01 | |||
| ee1f948448 | |||
| 995c7d349e | |||
| 4389160a6a | |||
| 8c6295658b | |||
| a270e342b7 | |||
| 42e2266530 | |||
| 02e6d729c1 | |||
| baac9a0578 | |||
| b73dd46521 | |||
| 7bbb2070a7 | |||
| 8859518f2d | |||
| 7f063c71b5 | |||
| 1e9691a7c0 | |||
| e5269bcf95 | |||
| fdd76a6ca1 | |||
| d19525c269 | |||
| 593331dec2 | |||
| b780d90097 | |||
| 2f9ce790e4 | |||
| d8f4519b0c | |||
| 702e41f55d | |||
| 682ac29fcd | |||
| c6ce23d0af | |||
| 9ae7d2dd9d | |||
| 6ec05628d5 | |||
| f26ebdc2f1 | |||
| c97255fc08 | |||
| 9d1ede016b | |||
| 7eb8f2452c | |||
| 0a6e691222 | |||
| 238aca6a78 | |||
| 1f039b3adc | |||
| 219465d599 | |||
| 1963cee94a | |||
| ae43e05f6f | |||
| 5cd2ba7296 | |||
| 4a00018f25 | |||
| 32c725e770 | |||
| 4e2ee35125 | |||
| 35b0751714 | |||
| 28ebc0ccd8 | |||
| 3d693d88e0 | |||
| 6ddf31d465 | |||
| 5c1ea707ca | |||
| a6669f89a0 | |||
| 2a2d509c36 | |||
| fd4efb3f33 | |||
| e90ab0b898 | |||
| 44367c54da | |||
| 3273a65889 | |||
| 0aa606d835 | |||
| 40848e7432 | |||
| fe4cc4d58c | |||
| 56f90ffaf3 | |||
| dfb556339f | |||
| 61f5a7f437 | |||
| 3be9b8d076 | |||
| 2a138dee40 | |||
| 712ef74b81 | |||
| ba8ca424cf | |||
| c6784a779b | |||
| d667cb7e57 | |||
| 10a5c2ed1d | |||
| 8cce78c890 | |||
| 294ade8aad | |||
| a59e8411c9 | |||
| d973f437ef | |||
| d5ce2c1431 | |||
| 834e2a99e3 | |||
| f8e9e33347 | |||
| a0c7781296 | |||
| 2ea998983d | |||
| e44b220b84 | |||
| 756cccb114 | |||
| af9982b804 | |||
| 1b946a18d2 | |||
| a397bfd549 | |||
| d276ac6857 |
@@ -7,7 +7,7 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please search existing issues to avoid duplicates.
|
||||
<!-- Please search existing issues to avoid duplicates. -->
|
||||
|
||||
## Details
|
||||
|
||||
@@ -28,5 +28,5 @@ inspectdr | | |
|
||||
### Versions
|
||||
|
||||
Plots.jl version:
|
||||
Backend version:
|
||||
Backend version (`]st -m`):
|
||||
Output of `versioninfo()`:
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
name = "Plots"
|
||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
author = ["Tom Breloff (@tbreloff)"]
|
||||
version = "1.1.3"
|
||||
version = "1.3.6"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
@@ -35,7 +35,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
Contour = "0.5"
|
||||
FFMPEG = "0.2, 0.3"
|
||||
FixedPointNumbers = "0.6, 0.7, 0.8"
|
||||
GR = "0.46, 0.47, 0.48"
|
||||
GR = "0.46, 0.47, 0.48, 0.49"
|
||||
GeometryTypes = "0.7, 0.8"
|
||||
JSON = "0.21"
|
||||
Measures = "0.3"
|
||||
@@ -44,9 +44,9 @@ PGFPlotsX = "1.2.0"
|
||||
PlotThemes = "2"
|
||||
PlotUtils = "1"
|
||||
RecipesBase = "1"
|
||||
RecipesPipeline = "0.1.3"
|
||||
RecipesPipeline = "0.1.7"
|
||||
Reexport = "0.2"
|
||||
Requires = "0.5, 1"
|
||||
Requires = "1"
|
||||
Showoff = "0.3.1"
|
||||
StatsBase = "0.32, 0.33"
|
||||
julia = "1"
|
||||
|
||||
@@ -108,6 +108,7 @@ export
|
||||
gif,
|
||||
mov,
|
||||
mp4,
|
||||
webm,
|
||||
animate,
|
||||
@animate,
|
||||
@gif,
|
||||
|
||||
+4
-2
@@ -24,6 +24,7 @@ end
|
||||
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
|
||||
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov")
|
||||
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4")
|
||||
webmfn() = (isijulia() ? "tmp.webm" : tempname()*".webm")
|
||||
|
||||
mutable struct FrameIterator
|
||||
itr
|
||||
@@ -63,6 +64,7 @@ file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
|
||||
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim, fn; kw...)
|
||||
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim, fn, false; kw...)
|
||||
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim, fn, false; kw...)
|
||||
webm(anim::Animation, fn = webmfn(); kw...) = buildanimation(anim, fn, false; kw...)
|
||||
|
||||
ffmpeg_framerate(fps) = "$fps"
|
||||
ffmpeg_framerate(fps::Rational) = "$(fps.num)/$(fps.den)"
|
||||
@@ -110,8 +112,8 @@ function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
|
||||
ext = file_extension(agif.filename)
|
||||
if ext == "gif"
|
||||
html = "<img src=\"data:image/gif;base64," * base64encode(read(agif.filename)) * "\" />"
|
||||
elseif ext in ("mov", "mp4")
|
||||
mimetype = ext == "mov" ? "video/quicktime" : "video/mp4"
|
||||
elseif ext in ("mov", "mp4","webm")
|
||||
mimetype = ext == "mov" ? "video/quicktime" : "video/$ext"
|
||||
html = "<video controls><source src=\"data:$mimetype;base64," *
|
||||
base64encode(read(agif.filename)) *
|
||||
"\" type = \"$mimetype\"></video>"
|
||||
|
||||
+3
-2
@@ -70,7 +70,7 @@ const _arg_desc = KW(
|
||||
:dpi => "Number. Dots Per Inch of output figures",
|
||||
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
|
||||
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
||||
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
||||
:extra_kwargs => "Either one of (`:plot`, `:subplot`, `:series`) to specify for which element extra keyword args are collected or a KW (Dict{Symbol,Any}) to pass a map of extra keyword args which may be specific to a backend. Default: `:series`.\n Example: `pgfplotsx(); scatter(1:5, extra_kwargs=Dict(:subplot=>Dict(\"axis line shift\" => \"10pt\"))`",
|
||||
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
|
||||
:warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes",
|
||||
|
||||
@@ -97,6 +97,7 @@ const _arg_desc = KW(
|
||||
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
|
||||
:legendfontrotation => "Real. Font rotation of legend entries",
|
||||
:legendfontcolor => "Color Type. Font color of legend entries",
|
||||
:legendtitle => "String. Legend title.",
|
||||
:legendtitlefontfamily => "String or Symbol. Font family of the legend title.",
|
||||
:legendtitlefontsize => "Integer. Font pointsize the legend title.",
|
||||
:legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center",
|
||||
@@ -104,7 +105,7 @@ const _arg_desc = KW(
|
||||
:legendtitlefontrotation => "Real. Font rotation of the legend title",
|
||||
:legendtitlefontcolor => "Color Type. Font color of the legend title",
|
||||
:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)",
|
||||
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
|
||||
:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.",
|
||||
:legendfont => "Font. Font of legend items.",
|
||||
:legendtitlefont => "Font. Font of the legend title.",
|
||||
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
|
||||
|
||||
+18
-10
@@ -281,6 +281,7 @@ const _series_defaults = KW(
|
||||
# one logical series to be broken up (path and markers, for example)
|
||||
:hover => nothing, # text to display when hovering over the data points
|
||||
:stride => (1,1), # array stride for wireframe/surface, the first element is the row stride and the second is the column stride.
|
||||
:extra_kwargs => Dict()
|
||||
)
|
||||
|
||||
|
||||
@@ -292,7 +293,7 @@ const _plot_defaults = KW(
|
||||
:fontfamily => "sans-serif",
|
||||
:size => (600,400),
|
||||
:pos => (0,0),
|
||||
:window_title => "Plots.jl",
|
||||
:window_title => "Plots.jl",
|
||||
:show => false,
|
||||
:layout => 1,
|
||||
:link => :none,
|
||||
@@ -304,8 +305,9 @@ const _plot_defaults = KW(
|
||||
:dpi => DPI, # dots per inch for images, etc
|
||||
:thickness_scaling => 1,
|
||||
:display_type => :auto,
|
||||
:extra_kwargs => KW(),
|
||||
:warn_on_unsupported => true,
|
||||
:extra_plot_kwargs => Dict(),
|
||||
:extra_kwargs => :series, # directs collection of extra_kwargs
|
||||
)
|
||||
|
||||
|
||||
@@ -354,6 +356,7 @@ const _subplot_defaults = KW(
|
||||
:colorbar_title => "",
|
||||
:framestyle => :axes,
|
||||
:camera => (30,30),
|
||||
:extra_kwargs => Dict()
|
||||
)
|
||||
|
||||
const _axis_defaults = KW(
|
||||
@@ -580,6 +583,7 @@ add_aliases(:fill_z, :fillz, :fz, :surfacecolor, :surfacecolour, :sc, :surfcolor
|
||||
add_aliases(:legend, :leg, :key)
|
||||
add_aliases(:legendtitle, :legend_title, :labeltitle, :label_title, :leg_title, :key_title)
|
||||
add_aliases(:colorbar, :cb, :cbar, :colorkey)
|
||||
add_aliases(:colorbar_title, :colorbartitle, :cb_title, :cbtitle, :cbartitle, :cbar_title, :colorkeytitle, :colorkey_title)
|
||||
add_aliases(:clims, :clim, :cbarlims, :cbar_lims, :climits, :color_limits)
|
||||
add_aliases(:smooth, :regression, :reg)
|
||||
add_aliases(:levels, :nlevels, :nlev, :levs)
|
||||
@@ -656,7 +660,7 @@ function default(k::Symbol)
|
||||
return _axis_defaults_byletter[letter][key]
|
||||
end
|
||||
k == :letter && return k # for type recipe processing
|
||||
k in _suppress_warnings || error("Unknown key: ", k)
|
||||
return missing
|
||||
end
|
||||
|
||||
function default(k::Symbol, v)
|
||||
@@ -941,8 +945,9 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
|
||||
replaceAliases!(plotattributes, _keyAliases)
|
||||
|
||||
# handle axis args common to all axis
|
||||
args = RecipesPipeline.pop_kw!(plotattributes, :axis, ())
|
||||
for arg in wraptuple(args)
|
||||
args = wraptuple(RecipesPipeline.pop_kw!(plotattributes, :axis, ()))
|
||||
showarg = wraptuple(RecipesPipeline.pop_kw!(plotattributes, :showaxis, ()))
|
||||
for arg in wraptuple((args..., showarg...))
|
||||
for letter in (:x, :y, :z)
|
||||
process_axis_arg!(plotattributes, arg, letter)
|
||||
end
|
||||
@@ -1121,26 +1126,29 @@ const _already_warned = Dict{Symbol,Set{Symbol}}()
|
||||
const _to_warn = Set{Symbol}()
|
||||
|
||||
function warn_on_unsupported_args(pkg::AbstractBackend, plotattributes)
|
||||
if !get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
|
||||
return
|
||||
end
|
||||
empty!(_to_warn)
|
||||
bend = backend_name(pkg)
|
||||
already_warned = get!(_already_warned, bend, Set{Symbol}())
|
||||
extra_kwargs = Dict{Symbol,Any}()
|
||||
for k in keys(plotattributes)
|
||||
is_attr_supported(pkg, k) && continue
|
||||
k in _suppress_warnings && continue
|
||||
if plotattributes[k] != default(k)
|
||||
default_value = default(k)
|
||||
if ismissing(default_value)
|
||||
extra_kwargs[k] = pop_kw!(plotattributes, k)
|
||||
elseif plotattributes[k] != default(k)
|
||||
k in already_warned || push!(_to_warn, k)
|
||||
end
|
||||
end
|
||||
|
||||
if !isempty(_to_warn)
|
||||
if !isempty(_to_warn) &&
|
||||
!get(plotattributes, :warn_on_unsupported, _plot_defaults[:warn_on_unsupported])
|
||||
for k in sort(collect(_to_warn))
|
||||
push!(already_warned, k)
|
||||
@warn("Keyword argument $k not supported with $pkg. Choose from: $(supported_attrs(pkg))")
|
||||
end
|
||||
end
|
||||
return extra_kwargs
|
||||
end
|
||||
|
||||
# _markershape_supported(pkg::AbstractBackend, shape::Symbol) = shape in supported_markers(pkg)
|
||||
|
||||
@@ -35,7 +35,6 @@ end
|
||||
function process_axis_arg!(plotattributes::AKW, arg, letter = "")
|
||||
T = typeof(arg)
|
||||
arg = get(_scaleAliases, arg, arg)
|
||||
|
||||
if typeof(arg) <: Font
|
||||
plotattributes[Symbol(letter,:tickfont)] = arg
|
||||
plotattributes[Symbol(letter,:guidefont)] = arg
|
||||
|
||||
+7
-2
@@ -190,11 +190,15 @@ function backend(sym::Symbol)
|
||||
end
|
||||
end
|
||||
|
||||
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize]
|
||||
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize, :pgfplots]
|
||||
|
||||
function warn_on_deprecated_backend(bsym::Symbol)
|
||||
if bsym in _deprecated_backends
|
||||
@warn("Backend $bsym has been deprecated.")
|
||||
if bsym == :pgfplots
|
||||
@warn("Backend $bsym has been deprecated. Use pgfplotsx instead.")
|
||||
else
|
||||
@warn("Backend $bsym has been deprecated.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -828,6 +832,7 @@ const _pgfplotsx_seriestype = [
|
||||
:heatmap,
|
||||
:contour,
|
||||
:contour3d,
|
||||
:quiver,
|
||||
:shape,
|
||||
:steppre,
|
||||
:stepmid,
|
||||
|
||||
+237
-177
@@ -148,7 +148,7 @@ function gr_polyline(x, y, func = GR.polyline; arrowside = :none, arrowstyle = :
|
||||
end
|
||||
end
|
||||
|
||||
function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowstyle = :simple)
|
||||
function gr_polyline3d(x, y, z, func = GR.polyline3d)
|
||||
iend = 0
|
||||
n = length(x)
|
||||
while iend < n-1
|
||||
@@ -176,14 +176,6 @@ function gr_polyline3d(x, y, z, func = GR.polyline3d; arrowside = :none, arrowst
|
||||
# if we found a start and end, draw the line segment, otherwise we're done
|
||||
if istart > 0 && iend > 0
|
||||
func(x[istart:iend], y[istart:iend], z[istart:iend])
|
||||
if arrowside in (:head,:both)
|
||||
gr_set_arrowstyle(arrowstyle)
|
||||
GR.drawarrow(x[iend-1], y[iend-1], z[iend-1], x[iend], y[iend], z[iend])
|
||||
end
|
||||
if arrowside in (:tail,:both)
|
||||
gr_set_arrowstyle(arrowstyle)
|
||||
GR.drawarrow(x[istart+1], y[istart+1], z[istart+1], x[istart], y[istart], z[istart])
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
@@ -228,7 +220,9 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
|
||||
|
||||
#draw angular grid
|
||||
if xaxis[:grid]
|
||||
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid], sp
|
||||
)
|
||||
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
|
||||
for i in eachindex(α)
|
||||
GR.polyline([sinf[i], 0], [cosf[i], 0])
|
||||
@@ -237,7 +231,9 @@ function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
|
||||
|
||||
#draw radial grid
|
||||
if yaxis[:grid]
|
||||
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid], sp
|
||||
)
|
||||
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
|
||||
for i in eachindex(rtick_values)
|
||||
r = (rtick_values[i] - rmin) / (rmax - rmin)
|
||||
@@ -301,7 +297,7 @@ function gr_draw_marker(series, xi, yi, clims, i, msize, strokewidth, shape::Sha
|
||||
sx, sy = coords(shape)
|
||||
# convert to ndc coords (percentages of window)
|
||||
GR.selntran(0)
|
||||
w, h = gr_plot_size
|
||||
w, h = get_size(series)
|
||||
f = msize / (w + h)
|
||||
xi, yi = GR.wctondc(xi, yi)
|
||||
xs = xi .+ sx .* f
|
||||
@@ -315,14 +311,14 @@ function gr_draw_marker(series, xi, yi, clims, i, msize, strokewidth, shape::Sha
|
||||
|
||||
# draw the shapes
|
||||
msc = get_markerstrokecolor(series, i)
|
||||
gr_set_line(strokewidth, :solid, msc)
|
||||
gr_set_line(strokewidth, :solid, msc, series)
|
||||
gr_set_transparency(msc, get_markerstrokealpha(series, i))
|
||||
GR.polyline(xs, ys)
|
||||
GR.selntran(1)
|
||||
end
|
||||
|
||||
function nominal_size()
|
||||
w, h = gr_plot_size
|
||||
function nominal_size(s)
|
||||
w, h = get_size(s)
|
||||
min(w, h) / 500
|
||||
end
|
||||
|
||||
@@ -333,7 +329,7 @@ function gr_draw_marker(series, xi, yi, clims, i, msize, strokewidth, shape::Sym
|
||||
gr_set_markercolor(get_markercolor(series, clims, i));
|
||||
gr_set_transparency(get_markeralpha(series, i))
|
||||
GR.setmarkertype(gr_markertype(shape))
|
||||
GR.setmarkersize(0.3msize / nominal_size())
|
||||
GR.setmarkersize(0.3msize / nominal_size(series))
|
||||
GR.polymarker([xi], [yi])
|
||||
end
|
||||
|
||||
@@ -354,8 +350,8 @@ function gr_draw_markers(
|
||||
shapes = series[:markershape]
|
||||
if shapes != :none
|
||||
for i in eachindex(x)
|
||||
ms = _gr_thickness_scaling[1] * _cycle(msize, i)
|
||||
msw = _gr_thickness_scaling[1] * _cycle(strokewidth, i)
|
||||
ms = get_thickness_scaling(series) * _cycle(msize, i)
|
||||
msw = get_thickness_scaling(series) * _cycle(strokewidth, i)
|
||||
shape = _cycle(shapes, i)
|
||||
gr_draw_marker(series, x[i], y[i], clims, i, ms, msw, shape)
|
||||
end
|
||||
@@ -364,11 +360,10 @@ end
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
function gr_set_line(lw, style, c) #, a)
|
||||
function gr_set_line(lw, style, c, s) # s can be Subplot or Series
|
||||
GR.setlinetype(gr_linetype(style))
|
||||
w, h = gr_plot_size
|
||||
GR.setlinewidth(_gr_thickness_scaling[1] * max(0, lw / nominal_size()))
|
||||
gr_set_linecolor(c) #, a)
|
||||
GR.setlinewidth(get_thickness_scaling(s) * max(0, lw / nominal_size(s)))
|
||||
gr_set_linecolor(c)
|
||||
end
|
||||
|
||||
|
||||
@@ -378,15 +373,15 @@ function gr_set_fill(c) #, a)
|
||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||
end
|
||||
|
||||
# this stores the conversion from a font pointsize to "percentage of window height" (which is what GR uses)
|
||||
const _gr_point_mult = 0.0018 * ones(1)
|
||||
const _gr_thickness_scaling = ones(1)
|
||||
# this stores the conversion from a font pointsize to "percentage of window height"
|
||||
# (which is what GR uses). `s` can be a Series, Subplot or Plot
|
||||
gr_point_mult(s) = 1.5 * get_thickness_scaling(s) * px / pt / maximum(get_size(s))
|
||||
|
||||
# set the font attributes... assumes _gr_point_mult has been populated already
|
||||
function gr_set_font(f::Font; halign = f.halign, valign = f.valign,
|
||||
# set the font attributes.
|
||||
function gr_set_font(f::Font, s; halign = f.halign, valign = f.valign,
|
||||
color = f.color, rotation = f.rotation)
|
||||
family = lowercase(f.family)
|
||||
GR.setcharheight(_gr_point_mult[1] * f.pointsize)
|
||||
GR.setcharheight(gr_point_mult(s) * f.pointsize)
|
||||
GR.setcharup(sind(-rotation), cosd(-rotation))
|
||||
if haskey(gr_font_family, family)
|
||||
GR.settextfontprec(100 + gr_font_family[family], GR.TEXT_PRECISION_STRING)
|
||||
@@ -413,14 +408,6 @@ end
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# viewport plot area
|
||||
|
||||
# this stays constant for a given subplot while displaying that subplot.
|
||||
# values are [xmin, xmax, ymin, ymax]. they range [0,1].
|
||||
const viewport_plotarea = zeros(4)
|
||||
|
||||
# the size of the current plot in pixels
|
||||
const gr_plot_size = [600.0, 400.0]
|
||||
|
||||
function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, viewport_canvas)
|
||||
viewport = zeros(4)
|
||||
viewport[1] = viewport_canvas[2] * (left(bb) / w)
|
||||
@@ -434,7 +421,7 @@ function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, vi
|
||||
end
|
||||
|
||||
# change so we're focused on the viewport area
|
||||
function gr_set_viewport_cmap(sp::Subplot)
|
||||
function gr_set_viewport_cmap(sp::Subplot, viewport_plotarea)
|
||||
GR.setviewport(
|
||||
viewport_plotarea[2] + (RecipesPipeline.is3d(sp) ? 0.07 : 0.02),
|
||||
viewport_plotarea[2] + (RecipesPipeline.is3d(sp) ? 0.10 : 0.05),
|
||||
@@ -443,17 +430,7 @@ function gr_set_viewport_cmap(sp::Subplot)
|
||||
)
|
||||
end
|
||||
|
||||
# reset the viewport to the plot area
|
||||
function gr_set_viewport_plotarea()
|
||||
GR.setviewport(
|
||||
viewport_plotarea[1],
|
||||
viewport_plotarea[2],
|
||||
viewport_plotarea[3],
|
||||
viewport_plotarea[4]
|
||||
)
|
||||
end
|
||||
|
||||
function gr_set_viewport_polar()
|
||||
function gr_set_viewport_polar(viewport_plotarea)
|
||||
xmin, xmax, ymin, ymax = viewport_plotarea
|
||||
ymax -= 0.05 * (xmax - xmin)
|
||||
xcenter = 0.5 * (xmin + xmax)
|
||||
@@ -518,11 +495,11 @@ function _cbar_unique(values, propname)
|
||||
end
|
||||
|
||||
# add the colorbar
|
||||
function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
|
||||
function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims, viewport_plotarea)
|
||||
GR.savestate()
|
||||
xmin, xmax = gr_xy_axislims(sp)[1:2]
|
||||
zmin, zmax = clims[1:2]
|
||||
gr_set_viewport_cmap(sp)
|
||||
gr_set_viewport_cmap(sp, viewport_plotarea)
|
||||
GR.setscale(0)
|
||||
GR.setwindow(xmin, xmax, zmin, zmax)
|
||||
if !isempty(cbar.gradients)
|
||||
@@ -555,9 +532,12 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
|
||||
if !isempty(cbar.lines)
|
||||
series = cbar.lines
|
||||
gr_set_gradient(_cbar_unique(get_colorgradient.(series),"color"))
|
||||
gr_set_line(_cbar_unique(get_linewidth.(series), "line width"),
|
||||
_cbar_unique(get_linestyle.(series), "line style"),
|
||||
_cbar_unique(get_linecolor.(series, Ref(clims)), "line color"))
|
||||
gr_set_line(
|
||||
_cbar_unique(get_linewidth.(series), "line width"),
|
||||
_cbar_unique(get_linestyle.(series), "line style"),
|
||||
_cbar_unique(get_linecolor.(series, Ref(clims)), "line color"),
|
||||
sp,
|
||||
)
|
||||
gr_set_transparency(_cbar_unique(get_linealpha.(series), "line alpha"))
|
||||
levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels")
|
||||
colors = gr_colorbar_colors(last(series), clims)
|
||||
@@ -568,24 +548,25 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims)
|
||||
end
|
||||
|
||||
ztick = 0.5 * GR.tick(zmin, zmax)
|
||||
gr_set_line(1, :solid, plot_color(:black))
|
||||
gr_set_line(1, :solid, plot_color(:black), sp)
|
||||
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
|
||||
|
||||
gr_set_font(guidefont(sp[:yaxis]))
|
||||
gr_set_font(guidefont(sp[:yaxis]), sp)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
GR.setcharup(-1, 0)
|
||||
gr_text(viewport_plotarea[2] + 0.1,
|
||||
gr_view_ycenter(), sp[:colorbar_title])
|
||||
gr_text(
|
||||
viewport_plotarea[2] + 0.1, gr_view_ycenter(viewport_plotarea), sp[:colorbar_title]
|
||||
)
|
||||
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2])
|
||||
gr_view_ycenter() = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4])
|
||||
gr_view_xcenter(viewport_plotarea) = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2])
|
||||
gr_view_ycenter(viewport_plotarea) = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4])
|
||||
|
||||
function gr_legend_pos(sp::Subplot, w, h)
|
||||
function gr_legend_pos(sp::Subplot, w, h, viewport_plotarea)
|
||||
s = sp[:legend]
|
||||
typeof(s) <: Symbol || return gr_legend_pos(s, w, h)
|
||||
typeof(s) <: Symbol || return gr_legend_pos(s, w, h, viewport_plotarea)
|
||||
str = string(s)
|
||||
if str == "best"
|
||||
str = "topright"
|
||||
@@ -629,7 +610,7 @@ function gr_legend_pos(sp::Subplot, w, h)
|
||||
(xpos,ypos)
|
||||
end
|
||||
|
||||
function gr_legend_pos(v::Tuple{S,T},w,h) where {S<:Real, T<:Real}
|
||||
function gr_legend_pos(v::Tuple{S,T}, w, h, viewport_plotarea) where {S<:Real, T<:Real}
|
||||
xpos = v[1] * (viewport_plotarea[2] - viewport_plotarea[1]) + viewport_plotarea[1]
|
||||
ypos = v[2] * (viewport_plotarea[4] - viewport_plotarea[3]) + viewport_plotarea[3]
|
||||
(xpos,ypos)
|
||||
@@ -655,7 +636,6 @@ end
|
||||
function gr_display(plt::Plot, fmt="")
|
||||
GR.clearws()
|
||||
|
||||
_gr_thickness_scaling[1] = plt[:thickness_scaling]
|
||||
dpi_factor = plt[:dpi] / Plots.DPI
|
||||
if fmt == "svg"
|
||||
dpi_factor *= 4
|
||||
@@ -668,8 +648,7 @@ function gr_display(plt::Plot, fmt="")
|
||||
|
||||
# compute the viewport_canvas, normalized to the larger dimension
|
||||
viewport_canvas = Float64[0,1,0,1]
|
||||
w, h = plt[:size]
|
||||
gr_plot_size[:] = [w, h]
|
||||
w, h = get_size(plt)
|
||||
if w > h
|
||||
ratio = float(h) / w
|
||||
msize = display_width_ratio * w * dpi_factor
|
||||
@@ -689,10 +668,6 @@ function gr_display(plt::Plot, fmt="")
|
||||
# fill in the viewport_canvas background
|
||||
gr_fill_viewport(viewport_canvas, plt[:background_color_outside])
|
||||
|
||||
# update point mult
|
||||
px_per_pt = px / pt
|
||||
_gr_point_mult[1] = 1.5 * _gr_thickness_scaling[1] * px_per_pt / max(h,w)
|
||||
|
||||
# subplots:
|
||||
for sp in plt.subplots
|
||||
gr_display(sp, w*px, h*px, viewport_canvas)
|
||||
@@ -705,10 +680,13 @@ end
|
||||
function gr_set_xticks_font(sp)
|
||||
flip = sp[:yaxis][:flip]
|
||||
mirror = sp[:xaxis][:mirror]
|
||||
gr_set_font(tickfont(sp[:xaxis]),
|
||||
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
|
||||
valign = (mirror ? :bottom : :top),
|
||||
rotation = sp[:xaxis][:rotation])
|
||||
gr_set_font(
|
||||
tickfont(sp[:xaxis]),
|
||||
sp,
|
||||
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
|
||||
valign = (mirror ? :bottom : :top),
|
||||
rotation = sp[:xaxis][:rotation],
|
||||
)
|
||||
return flip, mirror
|
||||
end
|
||||
|
||||
@@ -716,10 +694,13 @@ end
|
||||
function gr_set_yticks_font(sp)
|
||||
flip = sp[:xaxis][:flip]
|
||||
mirror = sp[:yaxis][:mirror]
|
||||
gr_set_font(tickfont(sp[:yaxis]),
|
||||
halign = (mirror ? :left : :right),
|
||||
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
|
||||
rotation = sp[:yaxis][:rotation])
|
||||
gr_set_font(
|
||||
tickfont(sp[:yaxis]),
|
||||
sp,
|
||||
halign = (mirror ? :left : :right),
|
||||
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
|
||||
rotation = sp[:yaxis][:rotation],
|
||||
)
|
||||
return flip, mirror
|
||||
end
|
||||
|
||||
@@ -760,9 +741,9 @@ function gr_get_ticks_size(ticks, rot)
|
||||
return w, h
|
||||
end
|
||||
|
||||
gr_tick_label(axis,label) = (axis[:formatter] in (:scientific, :auto)) ?
|
||||
gr_convert_sci_tick_label(label) :
|
||||
label
|
||||
gr_tick_label(axis, label) =
|
||||
(axis[:formatter] in (:scientific, :auto)) ? gr_convert_sci_tick_label(string(label)) :
|
||||
string(label)
|
||||
|
||||
function gr_convert_sci_tick_label(label)
|
||||
caret_split = split(label,'^')
|
||||
@@ -774,24 +755,28 @@ function gr_convert_sci_tick_label(label)
|
||||
end
|
||||
|
||||
function gr_axis_height(sp, axis)
|
||||
GR.savestate()
|
||||
ticks = get_ticks(sp, axis)
|
||||
gr_set_font(tickfont(axis))
|
||||
gr_set_font(tickfont(axis), sp)
|
||||
h = (ticks in (nothing, false, :none) ? 0 : last(gr_get_ticks_size(ticks, axis[:rotation])))
|
||||
if axis[:guide] != ""
|
||||
gr_set_font(guidefont(axis))
|
||||
gr_set_font(guidefont(axis), sp)
|
||||
h += last(gr_text_size(axis[:guide]))
|
||||
end
|
||||
GR.restorestate()
|
||||
return h
|
||||
end
|
||||
|
||||
function gr_axis_width(sp, axis)
|
||||
GR.savestate()
|
||||
ticks = get_ticks(sp, axis)
|
||||
gr_set_font(tickfont(axis))
|
||||
gr_set_font(tickfont(axis), sp)
|
||||
w = (ticks in (nothing, false, :none) ? 0 : first(gr_get_ticks_size(ticks, axis[:rotation])))
|
||||
if axis[:guide] != ""
|
||||
gr_set_font(guidefont(axis))
|
||||
gr_set_font(guidefont(axis), sp)
|
||||
w += last(gr_text_size(axis[:guide]))
|
||||
end
|
||||
GR.restorestate()
|
||||
return w
|
||||
end
|
||||
|
||||
@@ -810,9 +795,9 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
bottompad = 2mm + sp[:bottom_margin]
|
||||
# Add margin for title
|
||||
if sp[:title] != ""
|
||||
gr_set_font(titlefont(sp))
|
||||
gr_set_font(titlefont(sp), sp)
|
||||
l = last(last(gr_text_size(sp[:title])))
|
||||
h = 1mm + gr_plot_size[2] * l * px
|
||||
h = 1mm + get_size(sp)[2] * l * px
|
||||
toppad += h
|
||||
end
|
||||
|
||||
@@ -826,20 +811,22 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
tickfont(xaxis),
|
||||
halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
|
||||
valign = (xaxis[:mirror] ? :bottom : :top),
|
||||
rotation = xaxis[:rotation]
|
||||
rotation = xaxis[:rotation],
|
||||
sp
|
||||
)
|
||||
l = 0.01 + last(gr_get_ticks_size(xticks, xaxis[:rotation]))
|
||||
h = max(h, 1mm + gr_plot_size[2] * l * px)
|
||||
h = max(h, 1mm + get_size(sp)[2] * l * px)
|
||||
end
|
||||
if !(yticks in (nothing, false, :none))
|
||||
gr_set_font(
|
||||
tickfont(yaxis),
|
||||
halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
|
||||
valign = (yaxis[:mirror] ? :bottom : :top),
|
||||
rotation = yaxis[:rotation]
|
||||
rotation = yaxis[:rotation],
|
||||
sp
|
||||
)
|
||||
l = 0.01 + last(gr_get_ticks_size(yticks, yaxis[:rotation]))
|
||||
h = max(h, 1mm + gr_plot_size[2] * l * px)
|
||||
h = max(h, 1mm + get_size(sp)[2] * l * px)
|
||||
end
|
||||
if h > 0mm
|
||||
if xaxis[:mirror] || yaxis[:mirror]
|
||||
@@ -857,9 +844,10 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
|
||||
rotation = zaxis[:rotation],
|
||||
color = zaxis[:tickfontcolor],
|
||||
sp
|
||||
)
|
||||
l = 0.01 + first(gr_get_ticks_size(zticks, zaxis[:rotation]))
|
||||
w = 1mm + gr_plot_size[1] * l * px
|
||||
w = 1mm + get_size(sp)[1] * l * px
|
||||
if zaxis[:mirror]
|
||||
rightpad += w
|
||||
else
|
||||
@@ -870,14 +858,14 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
# Add margin for x or y label
|
||||
h = 0mm
|
||||
if xaxis[:guide] != ""
|
||||
gr_set_font(guidefont(sp[:xaxis]))
|
||||
gr_set_font(guidefont(sp[:xaxis]), sp)
|
||||
l = last(gr_text_size(sp[:xaxis][:guide]))
|
||||
h = max(h, 1mm + gr_plot_size[2] * l * px)
|
||||
h = max(h, 1mm + get_size(sp)[2] * l * px)
|
||||
end
|
||||
if yaxis[:guide] != ""
|
||||
gr_set_font(guidefont(sp[:yaxis]))
|
||||
gr_set_font(guidefont(sp[:yaxis]), sp)
|
||||
l = last(gr_text_size(sp[:yaxis][:guide]))
|
||||
h = max(h, 1mm + gr_plot_size[2] * l * px)
|
||||
h = max(h, 1mm + get_size(sp)[2] * l * px)
|
||||
end
|
||||
if h > 0mm
|
||||
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||
@@ -888,9 +876,9 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
end
|
||||
# Add margin for z label
|
||||
if zaxis[:guide] != ""
|
||||
gr_set_font(guidefont(sp[:zaxis]))
|
||||
gr_set_font(guidefont(sp[:zaxis]), sp)
|
||||
l = last(gr_text_size(sp[:zaxis][:guide]))
|
||||
w = 1mm + gr_plot_size[2] * l * px
|
||||
w = 1mm + get_size(sp)[2] * l * px
|
||||
if zaxis[:guide_position] == :right || (zaxis[:guide_position] == :auto && zaxis[:mirror] == true)
|
||||
rightpad += w
|
||||
else
|
||||
@@ -903,7 +891,7 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
if !(xticks in (nothing, false, :none))
|
||||
flip, mirror = gr_set_xticks_font(sp)
|
||||
l = 0.01 + last(gr_get_ticks_size(xticks, sp[:xaxis][:rotation]))
|
||||
h = 1mm + gr_plot_size[2] * l * px
|
||||
h = 1mm + get_size(sp)[2] * l * px
|
||||
if mirror
|
||||
toppad += h
|
||||
else
|
||||
@@ -913,7 +901,7 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
if !(yticks in (nothing, false, :none))
|
||||
flip, mirror = gr_set_yticks_font(sp)
|
||||
l = 0.01 + first(gr_get_ticks_size(yticks, sp[:yaxis][:rotation]))
|
||||
w = 1mm + gr_plot_size[1] * l * px
|
||||
w = 1mm + get_size(sp)[1] * l * px
|
||||
if mirror
|
||||
rightpad += w
|
||||
else
|
||||
@@ -923,9 +911,9 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
|
||||
# Add margin for x label
|
||||
if sp[:xaxis][:guide] != ""
|
||||
gr_set_font(guidefont(sp[:xaxis]))
|
||||
gr_set_font(guidefont(sp[:xaxis]), sp)
|
||||
l = last(gr_text_size(sp[:xaxis][:guide]))
|
||||
h = 1mm + gr_plot_size[2] * l * px
|
||||
h = 1mm + get_size(sp)[2] * l * px
|
||||
if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true)
|
||||
toppad += h
|
||||
else
|
||||
@@ -934,9 +922,9 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
||||
end
|
||||
# Add margin for y label
|
||||
if sp[:yaxis][:guide] != ""
|
||||
gr_set_font(guidefont(sp[:yaxis]))
|
||||
gr_set_font(guidefont(sp[:yaxis]), sp)
|
||||
l = last(gr_text_size(sp[:yaxis][:guide]))
|
||||
w = 1mm + gr_plot_size[2] * l * px
|
||||
w = 1mm + get_size(sp)[2] * l * px
|
||||
if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true)
|
||||
rightpad += w
|
||||
else
|
||||
@@ -960,7 +948,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# the viewports for this subplot
|
||||
viewport_subplot = gr_viewport_from_bbox(sp, bbox(sp), w, h, viewport_canvas)
|
||||
viewport_plotarea[:] = gr_viewport_from_bbox(sp, plotarea(sp), w, h, viewport_canvas)
|
||||
viewport_plotarea = gr_viewport_from_bbox(sp, plotarea(sp), w, h, viewport_canvas)
|
||||
# get data limits
|
||||
data_lims = gr_xy_axislims(sp)
|
||||
xy_lims = data_lims
|
||||
@@ -994,12 +982,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.selntran(0)
|
||||
GR.setscale(0)
|
||||
if sp[:legendtitle] !== nothing
|
||||
gr_set_font(legendtitlefont(sp))
|
||||
gr_set_font(legendtitlefont(sp), sp)
|
||||
tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle]))
|
||||
legendw = tbx[3] - tbx[1]
|
||||
legendn += 1
|
||||
end
|
||||
gr_set_font(legendfont(sp))
|
||||
gr_set_font(legendfont(sp), sp)
|
||||
for series in series_list(sp)
|
||||
should_add_to_legend(series) || continue
|
||||
legendn += 1
|
||||
@@ -1013,7 +1001,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
|
||||
dy = gr_point_mult(sp) * sp[:legendfontsize] * 1.75
|
||||
legendh = dy * legendn
|
||||
leg_str = string(sp[:legend])
|
||||
if occursin("outer", leg_str)
|
||||
@@ -1061,7 +1049,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
|
||||
# set our plot area view
|
||||
gr_set_viewport_plotarea()
|
||||
GR.setviewport(viewport_plotarea...)
|
||||
|
||||
# these are the Axis objects, which hold scale, lims, etc
|
||||
xaxis = sp[:xaxis]
|
||||
@@ -1102,7 +1090,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
|
||||
# draw the axes
|
||||
gr_set_font(tickfont(xaxis))
|
||||
gr_set_font(tickfont(xaxis), sp)
|
||||
GR.setlinewidth(sp.plt[:thickness_scaling])
|
||||
|
||||
if RecipesPipeline.is3d(sp)
|
||||
@@ -1121,33 +1109,63 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# draw the grid lines
|
||||
if xaxis[:grid]
|
||||
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
xaxis[:gridlinewidth],
|
||||
xaxis[:gridstyle],
|
||||
xaxis[:foreground_color_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
|
||||
gr_polyline3d(coords(xgrid_segs)...)
|
||||
end
|
||||
if yaxis[:grid]
|
||||
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
yaxis[:gridlinewidth],
|
||||
yaxis[:gridstyle],
|
||||
yaxis[:foreground_color_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
|
||||
gr_polyline3d(coords(ygrid_segs)...)
|
||||
end
|
||||
if zaxis[:grid]
|
||||
gr_set_line(zaxis[:gridlinewidth], zaxis[:gridstyle], zaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
zaxis[:gridlinewidth],
|
||||
zaxis[:gridstyle],
|
||||
zaxis[:foreground_color_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:gridalpha])
|
||||
gr_polyline3d(coords(zgrid_segs)...)
|
||||
end
|
||||
|
||||
if xaxis[:minorgrid]
|
||||
gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid])
|
||||
gr_set_line(
|
||||
xaxis[:minorgridlinewidth],
|
||||
xaxis[:minorgridstyle],
|
||||
xaxis[:foreground_color_minor_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha])
|
||||
gr_polyline3d(coords(xminorgrid_segs)...)
|
||||
end
|
||||
if yaxis[:minorgrid]
|
||||
gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid])
|
||||
gr_set_line(
|
||||
yaxis[:minorgridlinewidth],
|
||||
yaxis[:minorgridstyle],
|
||||
yaxis[:foreground_color_minor_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha])
|
||||
gr_polyline3d(coords(yminorgrid_segs)...)
|
||||
end
|
||||
if zaxis[:minorgrid]
|
||||
gr_set_line(zaxis[:minorgridlinewidth], zaxis[:minorgridstyle], zaxis[:foreground_color_minor_grid])
|
||||
gr_set_line(
|
||||
zaxis[:minorgridlinewidth],
|
||||
zaxis[:minorgridstyle],
|
||||
zaxis[:foreground_color_minor_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(zaxis[:foreground_color_minor_grid], zaxis[:minorgridalpha])
|
||||
gr_polyline3d(coords(zminorgrid_segs)...)
|
||||
end
|
||||
@@ -1155,17 +1173,17 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# axis lines
|
||||
if xaxis[:showaxis]
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_border])
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_border], sp)
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(xaxis_segs)...)
|
||||
end
|
||||
if yaxis[:showaxis]
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_border])
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_border], sp)
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(yaxis_segs)...)
|
||||
end
|
||||
if zaxis[:showaxis]
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_border])
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_border], sp)
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(zaxis_segs)...)
|
||||
end
|
||||
@@ -1174,30 +1192,39 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# axis ticks
|
||||
if xaxis[:showaxis]
|
||||
if sp[:framestyle] in (:zerolines, :grid)
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
|
||||
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0)
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_grid], sp)
|
||||
gr_set_transparency(
|
||||
xaxis[:foreground_color_grid],
|
||||
xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0
|
||||
)
|
||||
else
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis], sp)
|
||||
end
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(xtick_segs)...)
|
||||
end
|
||||
if yaxis[:showaxis]
|
||||
if sp[:framestyle] in (:zerolines, :grid)
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
|
||||
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0)
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_grid], sp)
|
||||
gr_set_transparency(
|
||||
yaxis[:foreground_color_grid],
|
||||
yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0
|
||||
)
|
||||
else
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis], sp)
|
||||
end
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(ytick_segs)...)
|
||||
end
|
||||
if zaxis[:showaxis]
|
||||
if sp[:framestyle] in (:zerolines, :grid)
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_grid])
|
||||
gr_set_transparency(zaxis[:foreground_color_grid], zaxis[:tick_direction] == :out ? zaxis[:gridalpha] : 0)
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_grid], sp)
|
||||
gr_set_transparency(
|
||||
zaxis[:foreground_color_grid],
|
||||
zaxis[:tick_direction] == :out ? zaxis[:gridalpha] : 0
|
||||
)
|
||||
else
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_axis])
|
||||
gr_set_line(1, :solid, zaxis[:foreground_color_axis], sp)
|
||||
end
|
||||
GR.setclip(0)
|
||||
gr_polyline3d(coords(ztick_segs)...)
|
||||
@@ -1213,6 +1240,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
valign = (xaxis[:mirror] ? :bottom : :top),
|
||||
rotation = xaxis[:rotation],
|
||||
color = xaxis[:tickfontcolor],
|
||||
sp
|
||||
)
|
||||
yt = if sp[:framestyle] == :origin
|
||||
0
|
||||
@@ -1244,6 +1272,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
valign = (yaxis[:mirror] ? :bottom : :top),
|
||||
rotation = yaxis[:rotation],
|
||||
color = yaxis[:tickfontcolor],
|
||||
sp
|
||||
)
|
||||
xt = if sp[:framestyle] == :origin
|
||||
0
|
||||
@@ -1275,6 +1304,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
valign = (:top, :vcenter, :bottom)[sign(zaxis[:rotation]) + 2],
|
||||
rotation = zaxis[:rotation],
|
||||
color = zaxis[:tickfontcolor],
|
||||
sp
|
||||
)
|
||||
xt = if sp[:framestyle] == :origin
|
||||
0
|
||||
@@ -1300,16 +1330,16 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# # border
|
||||
# intensity = sp[:framestyle] == :semi ? 0.5 : 1.0
|
||||
# if sp[:framestyle] in (:box, :semi)
|
||||
# gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
|
||||
# gr_set_line(intensity, :solid, xaxis[:foreground_color_border], sp)
|
||||
# gr_set_transparency(xaxis[:foreground_color_border], intensity)
|
||||
# gr_polyline3d(coords(xborder_segs)...)
|
||||
# gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
|
||||
# gr_set_line(intensity, :solid, yaxis[:foreground_color_border], sp)
|
||||
# gr_set_transparency(yaxis[:foreground_color_border], intensity)
|
||||
# gr_polyline3d(coords(yborder_segs)...)
|
||||
# end
|
||||
|
||||
elseif ispolar(sp)
|
||||
r = gr_set_viewport_polar()
|
||||
r = gr_set_viewport_polar(viewport_plotarea)
|
||||
#rmin, rmax = GR.adjustrange(ignorenan_minimum(r), ignorenan_maximum(r))
|
||||
rmin, rmax = axis_limits(sp, :y)
|
||||
gr_polaraxes(rmin, rmax, sp)
|
||||
@@ -1323,26 +1353,43 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# draw the grid lines
|
||||
if xaxis[:grid]
|
||||
# gr_set_linecolor(sp[:foreground_color_grid])
|
||||
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
|
||||
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
xaxis[:gridlinewidth],
|
||||
xaxis[:gridstyle],
|
||||
xaxis[:foreground_color_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:gridalpha])
|
||||
gr_polyline(coords(xgrid_segs)...)
|
||||
end
|
||||
if yaxis[:grid]
|
||||
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
|
||||
gr_set_line(
|
||||
yaxis[:gridlinewidth],
|
||||
yaxis[:gridstyle],
|
||||
yaxis[:foreground_color_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:gridalpha])
|
||||
gr_polyline(coords(ygrid_segs)...)
|
||||
end
|
||||
if xaxis[:minorgrid]
|
||||
# gr_set_linecolor(sp[:foreground_color_grid])
|
||||
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
|
||||
gr_set_line(xaxis[:minorgridlinewidth], xaxis[:minorgridstyle], xaxis[:foreground_color_minor_grid])
|
||||
gr_set_line(
|
||||
xaxis[:minorgridlinewidth],
|
||||
xaxis[:minorgridstyle],
|
||||
xaxis[:foreground_color_minor_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(xaxis[:foreground_color_minor_grid], xaxis[:minorgridalpha])
|
||||
gr_polyline(coords(xminorgrid_segs)...)
|
||||
end
|
||||
if yaxis[:minorgrid]
|
||||
gr_set_line(yaxis[:minorgridlinewidth], yaxis[:minorgridstyle], yaxis[:foreground_color_minor_grid])
|
||||
gr_set_line(
|
||||
yaxis[:minorgridlinewidth],
|
||||
yaxis[:minorgridstyle],
|
||||
yaxis[:foreground_color_minor_grid],
|
||||
sp
|
||||
)
|
||||
gr_set_transparency(yaxis[:foreground_color_minor_grid], yaxis[:minorgridalpha])
|
||||
gr_polyline(coords(yminorgrid_segs)...)
|
||||
end
|
||||
@@ -1350,12 +1397,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# axis lines
|
||||
if xaxis[:showaxis]
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_border])
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_border], sp)
|
||||
GR.setclip(0)
|
||||
gr_polyline(coords(xspine_segs)...)
|
||||
end
|
||||
if yaxis[:showaxis]
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_border])
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_border], sp)
|
||||
GR.setclip(0)
|
||||
gr_polyline(coords(yspine_segs)...)
|
||||
end
|
||||
@@ -1364,20 +1411,26 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# axis ticks
|
||||
if xaxis[:showaxis]
|
||||
if sp[:framestyle] in (:zerolines, :grid)
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
|
||||
gr_set_transparency(xaxis[:foreground_color_grid], xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0)
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_grid], sp)
|
||||
gr_set_transparency(
|
||||
xaxis[:foreground_color_grid],
|
||||
xaxis[:tick_direction] == :out ? xaxis[:gridalpha] : 0
|
||||
)
|
||||
else
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis], sp)
|
||||
end
|
||||
GR.setclip(0)
|
||||
gr_polyline(coords(xtick_segs)...)
|
||||
end
|
||||
if yaxis[:showaxis]
|
||||
if sp[:framestyle] in (:zerolines, :grid)
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
|
||||
gr_set_transparency(yaxis[:foreground_color_grid], yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0)
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_grid], sp)
|
||||
gr_set_transparency(
|
||||
yaxis[:foreground_color_grid],
|
||||
yaxis[:tick_direction] == :out ? yaxis[:gridalpha] : 0
|
||||
)
|
||||
else
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis], sp)
|
||||
end
|
||||
GR.setclip(0)
|
||||
gr_polyline(coords(ytick_segs)...)
|
||||
@@ -1410,10 +1463,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
intensity = sp[:framestyle] == :semi ? 0.5 : 1
|
||||
if sp[:framestyle] in (:box, :semi)
|
||||
GR.setclip(0)
|
||||
gr_set_line(intensity, :solid, xaxis[:foreground_color_border])
|
||||
gr_set_line(intensity, :solid, xaxis[:foreground_color_border], sp)
|
||||
gr_set_transparency(xaxis[:foreground_color_border], intensity)
|
||||
gr_polyline(coords(xborder_segs)...)
|
||||
gr_set_line(intensity, :solid, yaxis[:foreground_color_border])
|
||||
gr_set_line(intensity, :solid, yaxis[:foreground_color_border], sp)
|
||||
gr_set_transparency(yaxis[:foreground_color_border], intensity)
|
||||
gr_polyline(coords(yborder_segs)...)
|
||||
GR.setclip(1)
|
||||
@@ -1424,7 +1477,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# add the guides
|
||||
GR.savestate()
|
||||
if sp[:title] != ""
|
||||
gr_set_font(titlefont(sp))
|
||||
gr_set_font(titlefont(sp), sp)
|
||||
loc = sp[:titlelocation]
|
||||
if loc == :left
|
||||
xpos = viewport_plotarea[1]
|
||||
@@ -1433,7 +1486,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
xpos = viewport_plotarea[2]
|
||||
halign = GR.TEXT_HALIGN_RIGHT
|
||||
else
|
||||
xpos = gr_view_xcenter()
|
||||
xpos = gr_view_xcenter(viewport_plotarea)
|
||||
halign = GR.TEXT_HALIGN_CENTER
|
||||
end
|
||||
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
|
||||
@@ -1445,7 +1498,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
guidefont(xaxis),
|
||||
halign = (:left, :hcenter, :right)[sign(xaxis[:rotation]) + 2],
|
||||
valign = (xaxis[:mirror] ? :bottom : :top),
|
||||
rotation = xaxis[:rotation]
|
||||
rotation = xaxis[:rotation],
|
||||
sp
|
||||
)
|
||||
yg = xor(xaxis[:mirror], yaxis[:flip]) ? ymax : ymin
|
||||
zg = xor(xaxis[:mirror], zaxis[:flip]) ? zmax : zmin
|
||||
@@ -1460,7 +1514,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
guidefont(yaxis),
|
||||
halign = (:left, :hcenter, :right)[sign(yaxis[:rotation]) + 2],
|
||||
valign = (yaxis[:mirror] ? :bottom : :top),
|
||||
rotation = yaxis[:rotation]
|
||||
rotation = yaxis[:rotation],
|
||||
sp
|
||||
)
|
||||
xg = xor(yaxis[:mirror], xaxis[:flip]) ? xmin : xmax
|
||||
yg = (ymin + ymax) / 2
|
||||
@@ -1475,7 +1530,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
guidefont(zaxis),
|
||||
halign = (:left, :hcenter, :right)[sign(zaxis[:rotation]) + 2],
|
||||
valign = (zaxis[:mirror] ? :bottom : :top),
|
||||
rotation = zaxis[:rotation]
|
||||
rotation = zaxis[:rotation],
|
||||
sp
|
||||
)
|
||||
xg = xor(zaxis[:mirror], xaxis[:flip]) ? xmax : xmin
|
||||
yg = xor(zaxis[:mirror], yaxis[:flip]) ? ymax : ymin
|
||||
@@ -1488,32 +1544,32 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
else
|
||||
if xaxis[:guide] != ""
|
||||
h = 0.01 + gr_axis_height(sp, xaxis)
|
||||
gr_set_font(guidefont(xaxis))
|
||||
gr_set_font(guidefont(xaxis), sp)
|
||||
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(gr_view_xcenter(), viewport_plotarea[4] + h, xaxis[:guide])
|
||||
gr_text(gr_view_xcenter(viewport_plotarea), viewport_plotarea[4] + h, xaxis[:guide])
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_text(gr_view_xcenter(), viewport_plotarea[3] - h, xaxis[:guide])
|
||||
gr_text(gr_view_xcenter(viewport_plotarea), viewport_plotarea[3] - h, xaxis[:guide])
|
||||
end
|
||||
end
|
||||
|
||||
if yaxis[:guide] != ""
|
||||
w = 0.02 + gr_axis_width(sp, yaxis)
|
||||
gr_set_font(guidefont(yaxis))
|
||||
gr_set_font(guidefont(yaxis), sp)
|
||||
GR.setcharup(-1, 0)
|
||||
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_text(viewport_plotarea[2] + w, gr_view_ycenter(), yaxis[:guide])
|
||||
gr_text(viewport_plotarea[2] + w, gr_view_ycenter(viewport_plotarea), yaxis[:guide])
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(viewport_plotarea[1] - w, gr_view_ycenter(), yaxis[:guide])
|
||||
gr_text(viewport_plotarea[1] - w, gr_view_ycenter(viewport_plotarea), yaxis[:guide])
|
||||
end
|
||||
end
|
||||
end
|
||||
GR.restorestate()
|
||||
|
||||
gr_set_font(tickfont(xaxis))
|
||||
gr_set_font(tickfont(xaxis), sp)
|
||||
|
||||
# this needs to be here to point the colormap to the right indices
|
||||
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
||||
@@ -1528,7 +1584,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# update the bounding window
|
||||
if ispolar(sp)
|
||||
gr_set_viewport_polar()
|
||||
gr_set_viewport_polar(viewport_plotarea)
|
||||
else
|
||||
xmin, xmax, ymin, ymax = data_lims
|
||||
if xmax > xmin && ymax > ymin
|
||||
@@ -1581,7 +1637,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
if st in (:path, :straightline)
|
||||
for (i, rng) in enumerate(segments)
|
||||
lc = get_linecolor(series, clims, i)
|
||||
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha])
|
||||
gr_set_line(
|
||||
get_linewidth(series, i), get_linestyle(series, i), lc, sp
|
||||
)
|
||||
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
|
||||
arrowstyle = isa(series[:arrow], Arrow) ? series[:arrow].style : :simple
|
||||
gr_set_fillcolor(lc)
|
||||
@@ -1598,7 +1656,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
elseif st == :contour
|
||||
GR.setspace(clims[1], clims[2], 0, 90)
|
||||
GR.setlinetype(gr_linetype(get_linestyle(series)))
|
||||
GR.setlinewidth(max(0, get_linewidth(series)) / nominal_size())
|
||||
GR.setlinewidth(max(0, get_linewidth(series)) / nominal_size(sp))
|
||||
is_lc_black = let black=plot_color(:black)
|
||||
plot_color(series[:linecolor]) in (black,[black])
|
||||
end
|
||||
@@ -1688,7 +1746,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
segments = iter_segments(series)
|
||||
for (i, rng) in enumerate(segments)
|
||||
lc = get_linecolor(series, clims, i)
|
||||
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc) #, series[:linealpha])
|
||||
gr_set_line(
|
||||
get_linewidth(series, i), get_linestyle(series, i), lc, sp
|
||||
)
|
||||
gr_set_transparency(lc, get_linealpha(series, i))
|
||||
GR.polyline3d(x[rng], y[rng], z[rng])
|
||||
end
|
||||
@@ -1719,7 +1779,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# draw the shapes
|
||||
lc = get_linecolor(series, clims, i)
|
||||
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc)
|
||||
gr_set_line(get_linewidth(series, i), get_linestyle(series, i), lc, sp)
|
||||
gr_set_transparency(lc, get_linealpha(series, i))
|
||||
GR.polyline(xseg, yseg)
|
||||
end
|
||||
@@ -1739,12 +1799,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# this is all we need to add the series_annotations text
|
||||
anns = series[:series_annotations]
|
||||
for (xi,yi,str,fnt) in EachAnn(anns, x, y)
|
||||
gr_set_font(fnt)
|
||||
gr_set_font(fnt, sp)
|
||||
gr_text(GR.wctondc(xi, yi)..., str)
|
||||
end
|
||||
|
||||
if sp[:legend] == :inline && should_add_to_legend(series)
|
||||
gr_set_font(legendfont(sp))
|
||||
gr_set_font(legendfont(sp), sp)
|
||||
gr_set_textcolor(plot_color(sp[:legendfontcolor]))
|
||||
if sp[:yaxis][:mirror]
|
||||
(_,i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x)
|
||||
@@ -1762,39 +1822,39 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
|
||||
# draw the colorbar
|
||||
hascolorbar(sp) && gr_draw_colorbar(cbar, sp, get_clims(sp))
|
||||
hascolorbar(sp) && gr_draw_colorbar(cbar, sp, get_clims(sp), viewport_plotarea)
|
||||
|
||||
# add the legend
|
||||
if !(sp[:legend] in(:none, :inline))
|
||||
GR.savestate()
|
||||
GR.selntran(0)
|
||||
GR.setscale(0)
|
||||
gr_set_font(legendfont(sp))
|
||||
gr_set_font(legendfont(sp), sp)
|
||||
w = legendw
|
||||
n = legendn
|
||||
if w > 0
|
||||
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
|
||||
dy = gr_point_mult(sp) * sp[:legendfontsize] * 1.75
|
||||
h = dy*n
|
||||
xpos, ypos = gr_legend_pos(sp, w, h)
|
||||
xpos, ypos = gr_legend_pos(sp, w, h, viewport_plotarea)
|
||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||
gr_set_fillcolor(sp[:background_color_legend])
|
||||
GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
||||
gr_set_line(1, :solid, sp[:foreground_color_legend])
|
||||
gr_set_line(1, :solid, sp[:foreground_color_legend], sp)
|
||||
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
||||
i = 0
|
||||
if sp[:legendtitle] !== nothing
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
||||
gr_set_font(legendtitlefont(sp))
|
||||
gr_set_font(legendtitlefont(sp), sp)
|
||||
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
|
||||
ypos -= dy
|
||||
gr_set_font(legendfont(sp))
|
||||
gr_set_font(legendfont(sp), sp)
|
||||
end
|
||||
for series in series_list(sp)
|
||||
clims = get_clims(sp, series)
|
||||
should_add_to_legend(series) || continue
|
||||
st = series[:seriestype]
|
||||
lc = get_linecolor(series, clims)
|
||||
gr_set_line(sp[:legendfontsize] / 8, get_linestyle(series), lc) #, series[:linealpha])
|
||||
gr_set_line(sp[:legendfontsize] / 8, get_linestyle(series), lc, sp)
|
||||
|
||||
if (st == :shape || series[:fillrange] !== nothing) && series[:ribbon] === nothing
|
||||
fc = get_fillcolor(series, clims)
|
||||
@@ -1807,7 +1867,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
gr_polyline(x, y, GR.fillarea)
|
||||
lc = get_linecolor(series, clims)
|
||||
gr_set_transparency(lc, get_linealpha(series))
|
||||
gr_set_line(get_linewidth(series), get_linestyle(series), lc)
|
||||
gr_set_line(get_linewidth(series), get_linestyle(series), lc, sp)
|
||||
st == :shape && gr_polyline(x, y)
|
||||
end
|
||||
|
||||
@@ -1848,7 +1908,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.savestate()
|
||||
# update the bounding window
|
||||
if ispolar(sp)
|
||||
gr_set_viewport_polar()
|
||||
gr_set_viewport_polar(viewport_plotarea)
|
||||
else
|
||||
xmin, xmax, ymin, ymax = data_lims
|
||||
if xmax > xmin && ymax > ymin
|
||||
@@ -1862,7 +1922,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
else
|
||||
GR.wctondc(x, y)
|
||||
end
|
||||
gr_set_font(val.font)
|
||||
gr_set_font(val.font, sp)
|
||||
gr_text(x, y, val.str)
|
||||
end
|
||||
GR.restorestate()
|
||||
|
||||
+128
-75
@@ -86,7 +86,16 @@ end
|
||||
function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
if !pgfx_plot.is_created || pgfx_plot.was_shown
|
||||
pgfx_sanitize_plot!(plt)
|
||||
the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options())
|
||||
# extract extra kwargs
|
||||
extra_plot_opt = plt[:extra_plot_kwargs]
|
||||
extra_plot = nothing
|
||||
if haskey(extra_plot_opt, :add)
|
||||
extra_plot = wraptuple(pop!(extra_plot_opt,:add))
|
||||
end
|
||||
the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options(extra_plot_opt...))
|
||||
if extra_plot !== nothing
|
||||
push!(the_plot, extra_plot...)
|
||||
end
|
||||
bgc = plt.attr[:background_color_outside] == :match ?
|
||||
plt.attr[:background_color] : plt.attr[:background_color_outside]
|
||||
if bgc isa Colors.Colorant
|
||||
@@ -127,17 +136,12 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
bgc_inside = plot_color(sp[:background_color_inside])
|
||||
bgc_inside_a = alpha(bgc_inside)
|
||||
axis_opt = PGFPlotsX.Options(
|
||||
"point meta max" => get_clims(sp)[2],
|
||||
"point meta min" => get_clims(sp)[1],
|
||||
"legend cell align" => "left",
|
||||
"title" => sp[:title],
|
||||
"title style" => PGFPlotsX.Options(
|
||||
"at" => if title_loc == :left
|
||||
"{(0,1)}"
|
||||
elseif title_loc == :right
|
||||
"{(1,1)}"
|
||||
elseif title_loc isa Tuple
|
||||
"{$(string(title_loc))}"
|
||||
else
|
||||
"{(0.5,1)}"
|
||||
end,
|
||||
pgfx_get_title_pos(title_loc)...,
|
||||
"font" => pgfx_font(
|
||||
sp[:titlefontsize],
|
||||
pgfx_thickness_scaling(sp),
|
||||
@@ -175,12 +179,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
sp_height > 0 * mm ? push!(axis_opt, "height" => string(axis_height)) :
|
||||
nothing
|
||||
# legend position
|
||||
if sp[:legend] isa Tuple
|
||||
x, y = sp[:legend]
|
||||
push!(axis_opt["legend style"], "at={($x, $y)}")
|
||||
else
|
||||
push!(axis_opt["legend style"], pgfx_get_legend_pos(sp[:legend])...)
|
||||
end
|
||||
push!(axis_opt["legend style"], pgfx_get_legend_pos(sp[:legend])...)
|
||||
for letter in (:x, :y, :z)
|
||||
if letter != :z || RecipesPipeline.is3d(sp)
|
||||
pgfx_axis!(axis_opt, sp, letter)
|
||||
@@ -197,41 +196,48 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
# As it is likely that all series within the same axis use the same
|
||||
# colormap this should not cause any problem.
|
||||
for series in series_list(sp)
|
||||
if hascolorbar(series)
|
||||
cg = get_colorgradient(series)
|
||||
cm = pgfx_colormap(get_colorgradient(series))
|
||||
PGFPlotsX.push_preamble!(
|
||||
pgfx_plot.the_plot,
|
||||
"""\\pgfplotsset{
|
||||
colormap={plots$(sp.attr[:subplot_index])}{$cm},
|
||||
}""",
|
||||
)
|
||||
if hascolorbar(series)
|
||||
cg = get_colorgradient(series)
|
||||
cm = pgfx_colormap(get_colorgradient(series))
|
||||
PGFPlotsX.push_preamble!(
|
||||
pgfx_plot.the_plot,
|
||||
"""\\pgfplotsset{
|
||||
colormap={plots$(sp.attr[:subplot_index])}{$cm},
|
||||
}""",
|
||||
)
|
||||
push!(axis_opt, "colormap name" => "plots$(sp.attr[:subplot_index])")
|
||||
if cg isa PlotUtils.CategoricalColorGradient
|
||||
push!(
|
||||
axis_opt,
|
||||
"colorbar" => nothing,
|
||||
"colormap name" => "plots$(sp.attr[:subplot_index])",
|
||||
"colormap access" => "piecewise const",
|
||||
"colorbar sampled" => nothing,
|
||||
)
|
||||
if cg isa PlotUtils.CategoricalColorGradient
|
||||
push!(
|
||||
axis_opt,
|
||||
"colormap access" => "piecewise const",
|
||||
"colorbar sampled" => nothing,
|
||||
)
|
||||
end
|
||||
# goto is needed to break out of col and series for
|
||||
@goto colorbar_end
|
||||
end
|
||||
# goto is needed to break out of col and series for
|
||||
@goto colorbar_end
|
||||
end
|
||||
end
|
||||
@label colorbar_end
|
||||
|
||||
push!(
|
||||
axis_opt,
|
||||
"colorbar style" => PGFPlotsX.Options(
|
||||
if hascolorbar(sp)
|
||||
colorbar_style = PGFPlotsX.Options(
|
||||
"title" => sp[:colorbar_title],
|
||||
),
|
||||
"point meta max" => get_clims(sp)[2],
|
||||
"point meta min" => get_clims(sp)[1],
|
||||
)
|
||||
"xticklabel style" => pgfx_get_ticklabel_style(sp, sp[:xaxis]),
|
||||
"yticklabel style" => pgfx_get_ticklabel_style(sp, sp[:yaxis]),
|
||||
)
|
||||
if sp[:colorbar] === :top
|
||||
push!(colorbar_style,
|
||||
"at" => string((0.5, 1.05)),
|
||||
"anchor" => "south",
|
||||
"xticklabel pos" => "upper",
|
||||
)
|
||||
end
|
||||
push!(
|
||||
axis_opt,
|
||||
string("colorbar", pgfx_get_colorbar_pos(sp[:colorbar])) => nothing,
|
||||
"colorbar style" => colorbar_style,
|
||||
)
|
||||
end
|
||||
if RecipesPipeline.is3d(sp)
|
||||
azim, elev = sp[:camera]
|
||||
push!(axis_opt, "view" => (azim, elev))
|
||||
@@ -243,7 +249,15 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
else
|
||||
PGFPlotsX.Axis
|
||||
end
|
||||
axis = axisf(axis_opt)
|
||||
extra_sp_opt = sp[:extra_kwargs]
|
||||
extra_sp = nothing
|
||||
if haskey(extra_sp_opt, :add)
|
||||
extra_sp = wraptuple(pop!(extra_sp_opt,:add))
|
||||
end
|
||||
axis = axisf(merge(axis_opt, PGFPlotsX.Options(extra_sp_opt...)))
|
||||
if extra_sp !== nothing
|
||||
push!(axis, extra_sp...)
|
||||
end
|
||||
if sp[:legendtitle] !== nothing
|
||||
push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing))
|
||||
push!(
|
||||
@@ -265,7 +279,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
"color" => single_color(opt[:linecolor]),
|
||||
"name path" => string(series_id),
|
||||
)
|
||||
if RecipesPipeline.is3d(series) || st == :heatmap
|
||||
extra_series_opt = series[:extra_kwargs]
|
||||
extra_series = nothing
|
||||
if haskey(extra_series_opt, :add)
|
||||
extra_series = wraptuple(pop!(extra_series_opt,:add))
|
||||
end
|
||||
series_opt = merge(series_opt, PGFPlotsX.Options(extra_series_opt...))
|
||||
if RecipesPipeline.is3d(series) || st in (:heatmap, :contour)
|
||||
series_func = PGFPlotsX.Plot3
|
||||
else
|
||||
series_func = PGFPlotsX.Plot
|
||||
@@ -274,7 +294,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
!isfilledcontour(series) && series[:ribbon] === nothing
|
||||
push!(series_opt, "area legend" => nothing)
|
||||
end
|
||||
if st == :heatmap
|
||||
if st in (:heatmap, :contour)
|
||||
push!(axis.options, "view" => "{0}{90}")
|
||||
end
|
||||
# treat segments
|
||||
@@ -319,12 +339,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
end
|
||||
segment_opt = merge(segment_opt, pgfx_marker(opt, i))
|
||||
end
|
||||
if st == :shape || isfilledcontour(series)
|
||||
if st == :shape
|
||||
segment_opt = merge(segment_opt, pgfx_fillstyle(opt, i))
|
||||
end
|
||||
# add fillrange
|
||||
if sf !== nothing &&
|
||||
!isfilledcontour(series) && series[:ribbon] === nothing
|
||||
!isfilledcontour(series) &&
|
||||
series[:ribbon] === nothing
|
||||
if sf isa Number || sf isa AVec
|
||||
pgfx_fillrange_series!(
|
||||
axis,
|
||||
@@ -344,6 +365,9 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
pgfx_series_coordinates!(sp, series, segment_opt, opt, rng)
|
||||
segment_plot =
|
||||
series_func(merge(series_opt, segment_opt), coordinates)
|
||||
if extra_series !== nothing
|
||||
push!(segment_plot, extra_series...)
|
||||
end
|
||||
push!(axis, segment_plot)
|
||||
# fill between functions
|
||||
if sf isa Tuple && series[:ribbon] === nothing
|
||||
@@ -570,8 +594,8 @@ function pgfx_series_coordinates!(
|
||||
xs, ys, zs = collect(args)
|
||||
push!(
|
||||
segment_opt,
|
||||
"contour filled" => PGFPlotsX.Options("labels" => opt[:contour_labels]),
|
||||
"point meta" => "explicit",
|
||||
"contour filled" => PGFPlotsX.Options(), # labels not supported
|
||||
"patch type" => "bilinear",
|
||||
"shader" => "flat",
|
||||
)
|
||||
if opt[:levels] isa Number
|
||||
@@ -580,17 +604,7 @@ function pgfx_series_coordinates!(
|
||||
push!(segment_opt["contour filled"], "levels" => opt[:levels])
|
||||
end
|
||||
|
||||
cs = join(
|
||||
[
|
||||
join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") for (i, y) in enumerate(ys)
|
||||
],
|
||||
"\n\n",
|
||||
)
|
||||
"""
|
||||
coordinates {
|
||||
$cs
|
||||
};
|
||||
"""
|
||||
PGFPlotsX.Coordinates(args...)
|
||||
end
|
||||
##
|
||||
pgfx_get_linestyle(k) = get(
|
||||
@@ -629,6 +643,26 @@ pgfx_get_marker(k) = get(
|
||||
"*",
|
||||
)
|
||||
|
||||
pgfx_get_xguide_pos(k) = get(
|
||||
(
|
||||
top = "at={(0.5,1)},above,",
|
||||
right = "at={(ticklabel* cs:1.02)}, anchor=west,",
|
||||
left = "at={(ticklabel* cs:-0.02)}, anchor=east,",
|
||||
),
|
||||
k,
|
||||
"at={(ticklabel cs:0.5)}, anchor=near ticklabel"
|
||||
)
|
||||
|
||||
pgfx_get_yguide_pos(k) = get(
|
||||
(
|
||||
top = "at={(ticklabel* cs:1.02)}, anchor=south",
|
||||
right = "at={(1,0.5)},below,",
|
||||
bottom = "at={(ticklabel* cs:-0.02)}, anchor=north,",
|
||||
),
|
||||
k,
|
||||
"at={(ticklabel cs:0.5)}, anchor=near ticklabel"
|
||||
)
|
||||
|
||||
pgfx_get_legend_pos(k) = get(
|
||||
(
|
||||
top = ("at" => string((0.5, 0.98)), "anchor" => "north"),
|
||||
@@ -651,6 +685,33 @@ pgfx_get_legend_pos(k) = get(
|
||||
Symbol(k),
|
||||
("at" => string((1.02, 1)), "anchor" => "north west"),
|
||||
)
|
||||
pgfx_get_legend_pos(t::Tuple) = ("at" => "{$(string(t))}", "anchor" => "north west")
|
||||
pgfx_get_legend_pos(nt::NamedTuple) = ("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
|
||||
|
||||
pgfx_get_colorbar_pos(s) =
|
||||
get((left = " left", bottom = " horizontal", top = " horizontal"), s, "")
|
||||
pgfx_get_colorbar_pos(b::Bool) = ""
|
||||
|
||||
pgfx_get_title_pos(s) =
|
||||
get((
|
||||
left = ("at" => "{(0,1)}", "anchor" => "south west"),
|
||||
right = ("at" => "{(1,1)}", "anchor" => "south east"),
|
||||
), s,
|
||||
("at" => "{(0.5,1)}", "anchor" => "south"))
|
||||
pgfx_get_title_pos(t::Tuple) = ("at" => "{$(string(t))}", "anchor" => "south")
|
||||
pgfx_get_title_pos(nt::NamedTuple) = ("at" => "{$(string(nt.at))}", "anchor" => string(nt.anchor))
|
||||
|
||||
function pgfx_get_ticklabel_style(sp, axis)
|
||||
cstr = plot_color(axis[:tickfontcolor])
|
||||
return PGFPlotsX.Options(
|
||||
"font" => pgfx_font(
|
||||
axis[:tickfontsize], pgfx_thickness_scaling(sp)
|
||||
),
|
||||
"color" => cstr,
|
||||
"draw opacity" => alpha(cstr),
|
||||
"rotate" => axis[:tickfontrotation],
|
||||
)
|
||||
end
|
||||
|
||||
## --------------------------------------------------------------------------------------
|
||||
# Generates a colormap for pgfplots based on a ColorGradient
|
||||
@@ -992,10 +1053,10 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
|
||||
|
||||
# axis label position
|
||||
labelpos = ""
|
||||
if letter == :x && axis[:guide_position] == :top
|
||||
labelpos = "at={(0.5,1)},above,"
|
||||
elseif letter == :y && axis[:guide_position] == :right
|
||||
labelpos = "at={(1,0.5)},below,"
|
||||
if letter == :x
|
||||
labelpos = pgfx_get_xguide_pos(axis[:guide_position])
|
||||
elseif letter == :y
|
||||
labelpos = pgfx_get_yguide_pos(axis[:guide_position])
|
||||
end
|
||||
|
||||
# Add label font
|
||||
@@ -1088,17 +1149,8 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
|
||||
string(letter, "tick align") =>
|
||||
(axis[:tick_direction] == :out ? "outside" : "inside"),
|
||||
)
|
||||
cstr = plot_color(axis[:tickfontcolor])
|
||||
α = alpha(cstr)
|
||||
push!(
|
||||
opt,
|
||||
string(letter, "ticklabel style") => PGFPlotsX.Options(
|
||||
"font" =>
|
||||
pgfx_font(axis[:tickfontsize], pgfx_thickness_scaling(sp)),
|
||||
"color" => cstr,
|
||||
"draw opacity" => α,
|
||||
"rotate" => axis[:tickfontrotation],
|
||||
),
|
||||
opt, string(letter, "ticklabel style") => pgfx_get_ticklabel_style(sp, axis)
|
||||
)
|
||||
push!(
|
||||
opt,
|
||||
@@ -1186,6 +1238,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# display calls this and then _display, its called 3 times for plot(1:5)
|
||||
# Set the (left, top, right, bottom) minimum padding around the plot area
|
||||
|
||||
@@ -336,7 +336,7 @@ function plotly_layout(plt::Plot)
|
||||
plotattributes_out[:hovermode] = "none"
|
||||
end
|
||||
|
||||
plotattributes_out
|
||||
plotattributes_out = recursive_merge(plotattributes_out, plt.attr[:extra_plot_kwargs])
|
||||
end
|
||||
|
||||
function plotly_layout_json(plt::Plot)
|
||||
@@ -810,9 +810,14 @@ html_body(plt::Plot{PlotlyBackend}) = plotly_html_body(plt)
|
||||
const ijulia_initialized = Ref(false)
|
||||
|
||||
function plotly_html_head(plt::Plot)
|
||||
local_file = ("file://" * plotly_local_file_path)
|
||||
local_file = ("file:///" * plotly_local_file_path)
|
||||
plotly =
|
||||
use_local_dependencies[] ? local_file : "https://cdn.plot.ly/plotly-latest.min.js"
|
||||
|
||||
include_mathjax = get(plt[:extra_plot_kwargs], :include_mathjax, "")
|
||||
mathjax_file = include_mathjax != "cdn" ? ("file://" * include_mathjax) : "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML"
|
||||
mathjax_head = include_mathjax == "" ? "" : "<script src=\"$mathjax_file\"></script>\n\t\t"
|
||||
|
||||
if isijulia() && !ijulia_initialized[]
|
||||
# using requirejs seems to be key to load a js depency in IJulia!
|
||||
# https://requirejs.org/docs/start.html
|
||||
@@ -826,7 +831,7 @@ function plotly_html_head(plt::Plot)
|
||||
""")
|
||||
ijulia_initialized[] = true
|
||||
end
|
||||
return "<script src=$(repr(plotly))></script>"
|
||||
return "$mathjax_head<script src=$(repr(plotly))></script>"
|
||||
end
|
||||
|
||||
function plotly_html_body(plt, style = nothing)
|
||||
|
||||
+51
-24
@@ -13,6 +13,7 @@ append!(Base.Multimedia.displays, otherdisplays)
|
||||
pycolors = PyPlot.pyimport("matplotlib.colors")
|
||||
pypath = PyPlot.pyimport("matplotlib.path")
|
||||
mplot3d = PyPlot.pyimport("mpl_toolkits.mplot3d")
|
||||
axes_grid1 = PyPlot.pyimport("mpl_toolkits.axes_grid1")
|
||||
pypatches = PyPlot.pyimport("matplotlib.patches")
|
||||
pyfont = PyPlot.pyimport("matplotlib.font_manager")
|
||||
pyticker = PyPlot.pyimport("matplotlib.ticker")
|
||||
@@ -517,7 +518,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = py_marker(_cycle(shapes,i)),
|
||||
s = py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2),
|
||||
s = py_thickness_scale(plt, _cycle(series[:markersize],i)).^ 2,
|
||||
facecolors = py_color(get_markercolor(series, i), get_markercoloralpha(series, i)),
|
||||
edgecolors = msc,
|
||||
linewidths = lw,
|
||||
@@ -548,7 +549,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
push!(cur_y_list, _cycle(y,i))
|
||||
|
||||
push!(cur_color_list, _cycle(markercolor, i))
|
||||
push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2))
|
||||
push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i)).^ 2)
|
||||
|
||||
continue
|
||||
end
|
||||
@@ -558,7 +559,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = prev_marker,
|
||||
s = cur_scale_list,
|
||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)), # Do we need include i?
|
||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
||||
facecolors = cur_color_list,
|
||||
extrakw...
|
||||
@@ -568,7 +569,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
cur_y_list = [_cycle(y,i)]
|
||||
|
||||
cur_color_list = [_cycle(markercolor, i)]
|
||||
cur_scale_list = [py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)]
|
||||
cur_scale_list = [py_thickness_scale(plt, _cycle(series[:markersize],i)) .^ 2]
|
||||
|
||||
prev_marker = cur_marker
|
||||
end
|
||||
@@ -589,11 +590,17 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
push!(handles, handle)
|
||||
else
|
||||
# do a normal scatter plot
|
||||
|
||||
# Add depthshade option for 3d plots
|
||||
if RecipesPipeline.is3d(sp)
|
||||
extrakw[:depthshade] = get(series[:extra_kwargs], :depthshade, false)
|
||||
end
|
||||
|
||||
handle = ax."scatter"(xyargs...;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = py_marker(series[:markershape]),
|
||||
s = py_thickness_scale(plt, series[:markersize] .^ 2),
|
||||
s = py_thickness_scale(plt, series[:markersize]) .^2,
|
||||
edgecolors = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
||||
extrakw...
|
||||
@@ -603,14 +610,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st == :hexbin
|
||||
handle = ax."hexbin"(x, y;
|
||||
handle = ax."hexbin"(x, y,
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
gridsize = series[:bins],
|
||||
C = series[:weights],
|
||||
gridsize = series[:bins]==:auto ? 100 : series[:bins], # 100 is the default value
|
||||
linewidths = py_thickness_scale(plt, series[:linewidth]),
|
||||
edgecolors = py_color(get_linecolor(series)),
|
||||
alpha = series[:fillalpha],
|
||||
cmap = py_fillcolormap(series), # applies to the pcolorfast object
|
||||
extrakw...
|
||||
zorder = series[:series_plotindex],
|
||||
# extrakw... # We are not supporting clims for hexbin as calculation of bins is not trivial
|
||||
)
|
||||
push!(handles, handle)
|
||||
end
|
||||
@@ -643,7 +652,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
extrakw...
|
||||
)
|
||||
if series[:contour_labels] == true
|
||||
PyPlot."clabel"(handle, handle.levels)
|
||||
ax."clabel"(handle, handle.levels)
|
||||
end
|
||||
push!(handles, handle)
|
||||
|
||||
@@ -652,6 +661,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
handle = ax."contourf"(x, y, z, levelargs...;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
alpha = series[:fillalpha],
|
||||
extrakw...
|
||||
)
|
||||
push!(handles, handle)
|
||||
@@ -995,12 +1005,27 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
end
|
||||
kw[:spacing] = "proportional"
|
||||
|
||||
# create and store the colorbar object (handle) and the axis that it is drawn on.
|
||||
# note: the colorbar axis is positioned independently from the subplot axis
|
||||
fig = plt.o
|
||||
cbax = fig."add_axes"([0.8,0.1,0.03,0.8], label = string(gensym()))
|
||||
cb = fig."colorbar"(handle; cax = cbax, kw...)
|
||||
|
||||
if RecipesPipeline.is3d(sp)
|
||||
cbax = fig."add_axes"([0.9, 0.1, 0.03, 0.8])
|
||||
cb = fig."colorbar"(handle; cax=cbax, kw...)
|
||||
else
|
||||
# divider approach works only with 2d plots
|
||||
divider = axes_grid1.make_axes_locatable(ax)
|
||||
# width = axes_grid1.axes_size.AxesY(ax, aspect=1.0 / 3.5)
|
||||
# pad = axes_grid1.axes_size.Fraction(0.5, width) # Colorbar is spaced 0.5 of its size away from the ax
|
||||
# cbax = divider.append_axes("right", size=width, pad=pad) # This approach does not work well in subplots
|
||||
cbax = divider.append_axes("right", size="5%", pad="2.5%") # Reasonable value works most of the usecases
|
||||
cb = fig."colorbar"(handle; cax=cbax, kw...)
|
||||
end
|
||||
|
||||
cb."set_label"(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
|
||||
|
||||
# cb."formatter".set_useOffset(false) # This for some reason does not work, must be a pyplot bug, instead this is a workaround:
|
||||
cb."formatter".set_powerlimits((-Inf, Inf))
|
||||
cb."update_ticks"()
|
||||
|
||||
for lab in cb."ax"."yaxis"."get_ticklabels"()
|
||||
lab."set_fontsize"(py_thickness_scale(plt, sp[:yaxis][:tickfontsize]))
|
||||
lab."set_family"(sp[:yaxis][:tickfontfamily])
|
||||
@@ -1075,6 +1100,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize]))
|
||||
pyaxis."label"."set_family"(axis[:guidefontfamily])
|
||||
|
||||
if (RecipesPipeline.is3d(sp))
|
||||
pyaxis."set_rotate_label"(false)
|
||||
end
|
||||
|
||||
if (letter == :y && !RecipesPipeline.is3d(sp))
|
||||
pyaxis."label"."set_rotation"(axis[:guidefontrotation] + 90)
|
||||
else
|
||||
@@ -1208,7 +1237,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
|
||||
# optionally add the width of colorbar labels and colorbar to rightpad
|
||||
if haskey(sp.attr, :cbar_ax)
|
||||
bb = py_bbox(sp.attr[:cbar_handle]."ax"."get_yticklabels"())
|
||||
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||
sp.attr[:cbar_width] = _cbar_width + width(bb) + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||
rightpad = rightpad + sp.attr[:cbar_width]
|
||||
end
|
||||
|
||||
@@ -1307,16 +1336,17 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
||||
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
|
||||
linestyle = py_linestyle(series[:seriestype], get_linestyle(series))
|
||||
)
|
||||
elseif series[:seriestype] in (:path, :straightline, :scatter)
|
||||
elseif series[:seriestype] in (:path, :straightline, :scatter, :steppre, :steppost)
|
||||
hasline = get_linewidth(series) > 0
|
||||
PyPlot.plt."Line2D"((0,1),(0,0),
|
||||
color = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)),
|
||||
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
|
||||
linewidth = py_thickness_scale(plt, hasline * sp[:legendfontsize] / 8),
|
||||
linestyle = py_linestyle(:path, get_linestyle(series)),
|
||||
marker = py_marker(_cycle(series[:markershape], 1)),
|
||||
# markersize = py_thickness_scale(plt, series[:markersize]), # In case we decide that markersize needs to be scaled in the legend too
|
||||
markersize = py_thickness_scale(plt, 0.8 * sp[:legendfontsize]),
|
||||
markeredgecolor = py_color(single_color(get_markerstrokecolor(series)), get_markerstrokealpha(series)),
|
||||
markerfacecolor = py_color(single_color(get_markercolor(series, clims)), get_markeralpha(series)),
|
||||
markeredgewidth = py_thickness_scale(plt, series[:markerstrokewidth])
|
||||
markeredgewidth = py_thickness_scale(plt, 0.8 * get_markerstrokewidth(series) * sp[:legendfontsize] / first(series[:markersize])) # retain the markersize/markerstroke ratio from the markers on the plot
|
||||
)
|
||||
else
|
||||
series[:serieshandle][1]
|
||||
@@ -1368,13 +1398,10 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
|
||||
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
|
||||
ax."set_position"(pcts)
|
||||
|
||||
# set the cbar position if there is one
|
||||
if haskey(sp.attr, :cbar_ax)
|
||||
if haskey(sp.attr, :cbar_ax) && RecipesPipeline.is3d(sp) # 2D plots are completely handled by axis dividers
|
||||
cbw = sp.attr[:cbar_width]
|
||||
# this is the bounding box of just the colors of the colorbar (not labels)
|
||||
ex = sp[:zaxis][:extrema]
|
||||
has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7)
|
||||
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm))
|
||||
cb_bbox = BoundingBox(right(sp.bbox)-cbw - 2mm, top(sp.bbox) + 2mm, _cbar_width-1mm, height(sp.bbox) - 4mm)
|
||||
pcts = bbox_to_pcts(cb_bbox, figw, figh)
|
||||
sp.attr[:cbar_ax]."set_position"(pcts)
|
||||
end
|
||||
|
||||
@@ -998,13 +998,11 @@ _backend_skips = Dict(
|
||||
6, # images
|
||||
10, # histogram2d
|
||||
16, # pgfplots thinks the upper panel is too small
|
||||
22, # contourf
|
||||
25, # @df
|
||||
30, # @df
|
||||
31, # animation
|
||||
32, # spy
|
||||
38, # histogram2d
|
||||
45, # wireframe
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+1
-9
@@ -29,49 +29,41 @@ function __init__()
|
||||
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" begin
|
||||
fn = joinpath(@__DIR__, "backends", "hdf5.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" begin
|
||||
fn = joinpath(@__DIR__, "backends", "inspectdr.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" begin
|
||||
fn = joinpath(@__DIR__, "backends", "pgfplots.jl")
|
||||
fn = joinpath(@__DIR__, "backends", "deprecated", "pgfplots.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require ORCA = "47be7bcc-f1a6-5447-8b36-7eeeff7534fd" begin
|
||||
fn = joinpath(@__DIR__, "backends", "orca.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925" begin
|
||||
fn = joinpath(@__DIR__, "backends", "pgfplotsx.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" begin
|
||||
fn = joinpath(@__DIR__, "backends", "plotlyjs.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" begin
|
||||
fn = joinpath(@__DIR__, "backends", "pyplot.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" begin
|
||||
fn = joinpath(@__DIR__, "backends", "unicodeplots.jl")
|
||||
include(fn)
|
||||
@require Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Revise.track(Plots, fn)
|
||||
end
|
||||
|
||||
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
|
||||
|
||||
+30
-1
@@ -155,8 +155,23 @@ RecipesPipeline.type_alias(plt::Plot) = get(_typeAliases, st, st)
|
||||
function RecipesPipeline.plot_setup!(plt::Plot, plotattributes, kw_list)
|
||||
_plot_setup(plt, plotattributes, kw_list)
|
||||
_subplot_setup(plt, plotattributes, kw_list)
|
||||
return nothing
|
||||
end
|
||||
|
||||
function RecipesPipeline.process_sliced_series_attributes!(plt::Plots.Plot, kw_list)
|
||||
# swap errors
|
||||
err_inds = findall(kw -> get(kw, :seriestype, :path) in (:xerror, :yerror, :zerror), kw_list)
|
||||
for ind in err_inds
|
||||
if get(kw_list[ind-1],:seriestype,:path) == :scatter
|
||||
tmp = copy(kw_list[ind])
|
||||
kw_list[ind] = copy(kw_list[ind-1])
|
||||
kw_list[ind-1] = tmp
|
||||
end
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
|
||||
# TODO: Should some of this logic be moved to RecipesPipeline?
|
||||
function _plot_setup(plt::Plot, plotattributes::AKW, kw_list::Vector{KW})
|
||||
# merge in anything meant for the Plot
|
||||
@@ -274,6 +289,7 @@ function RecipesPipeline.slice_series_attributes!(plt::Plot, kw_list, kw)
|
||||
# in series attributes given as vector with one element per series,
|
||||
# select the value for current series
|
||||
_slice_series_args!(kw, plt, sp, series_idx(kw_list, kw))
|
||||
return nothing
|
||||
end
|
||||
|
||||
RecipesPipeline.series_defaults(plt::Plot) = _series_defaults # in args.jl
|
||||
@@ -341,7 +357,20 @@ function _expand_subplot_extrema(sp::Subplot, plotattributes::AKW, st::Symbol)
|
||||
end
|
||||
|
||||
function _add_the_series(plt, sp, plotattributes)
|
||||
warn_on_unsupported_args(plt.backend, plotattributes)
|
||||
extra_kwargs = warn_on_unsupported_args(plt.backend, plotattributes)
|
||||
if (kw = plt[:extra_kwargs]) isa AbstractDict
|
||||
plt[:extra_plot_kwargs] = get(kw,:plot,KW())
|
||||
sp[:extra_kwargs] = get(kw,:subplot, KW())
|
||||
plotattributes[:extra_kwargs] = get(kw,:series,KW())
|
||||
elseif plt[:extra_kwargs] == :plot
|
||||
plt[:extra_plot_kwargs] = extra_kwargs
|
||||
elseif plt[:extra_kwargs] == :subplot
|
||||
sp[:extra_kwargs] = extra_kwargs
|
||||
elseif plt[:extra_kwargs] == :series
|
||||
plotattributes[:extra_kwargs] = extra_kwargs
|
||||
else
|
||||
ArgumentError("Unsupported type for extra keyword arguments")
|
||||
end
|
||||
warn_on_unsupported(plt.backend, plotattributes)
|
||||
series = Series(plotattributes)
|
||||
push!(plt.series_list, series)
|
||||
|
||||
+15
-9
@@ -71,8 +71,9 @@ const POTENTIAL_VECTOR_ARGUMENTS = [
|
||||
:marker_z,
|
||||
:markerstrokecolor,
|
||||
:markerstrokealpha,
|
||||
:xerror,
|
||||
:yerror,
|
||||
:yerror,
|
||||
:zerror,
|
||||
:series_annotations,
|
||||
:fillrange,
|
||||
]
|
||||
@@ -111,7 +112,7 @@ end
|
||||
|
||||
@recipe function f(::Type{Val{:hline}}, x, y, z)
|
||||
n = length(y)
|
||||
newx = repeat(Float64[-1, 1, NaN], n)
|
||||
newx = repeat(Float64[1, 2, NaN], n)
|
||||
newy = vec(Float64[yi for i = 1:3, yi in y])
|
||||
x := newx
|
||||
y := newy
|
||||
@@ -123,7 +124,7 @@ end
|
||||
@recipe function f(::Type{Val{:vline}}, x, y, z)
|
||||
n = length(y)
|
||||
newx = vec(Float64[yi for i = 1:3, yi in y])
|
||||
newy = repeat(Float64[-1, 1, NaN], n)
|
||||
newy = repeat(Float64[1, 2, NaN], n)
|
||||
x := newx
|
||||
y := newy
|
||||
seriestype := :straightline
|
||||
@@ -459,7 +460,7 @@ end
|
||||
@deps plots_heatmap shape
|
||||
is_3d(::Type{Val{:plots_heatmap}}) = true
|
||||
RecipesPipeline.is_surface(::Type{Val{:plots_heatmap}}) = true
|
||||
|
||||
RecipesPipeline.is_surface(::Type{Val{:hexbin}}) = true
|
||||
# ---------------------------------------------------------------------------
|
||||
# Histograms
|
||||
|
||||
@@ -537,14 +538,19 @@ end
|
||||
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
||||
edge, weights, xscale, yscale, baseline =
|
||||
_preprocess_binlike(plotattributes, x, y)
|
||||
xerror := diff(edge) / 2
|
||||
@series begin
|
||||
x := _bin_centers(edge)
|
||||
xerror := diff(edge) / 2
|
||||
primary := false
|
||||
seriestype := :xerror
|
||||
()
|
||||
end
|
||||
x := _bin_centers(edge)
|
||||
y := weights
|
||||
seriestype := :scatter
|
||||
()
|
||||
end
|
||||
@deps scatterbins scatter
|
||||
|
||||
@deps scatterbins xerror scatter
|
||||
|
||||
function _stepbins_path(
|
||||
edge,
|
||||
@@ -1022,7 +1028,7 @@ end
|
||||
|
||||
function error_style!(plotattributes::AKW)
|
||||
plotattributes[:seriestype] = :path
|
||||
plotattributes[:linecolor] = plotattributes[:markerstrokecolor]
|
||||
plotattributes[:markercolor] = plotattributes[:markerstrokecolor]
|
||||
plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
|
||||
plotattributes[:label] = ""
|
||||
end
|
||||
@@ -1094,7 +1100,7 @@ end
|
||||
end
|
||||
()
|
||||
end
|
||||
@deps xerror path
|
||||
@deps zerror path
|
||||
|
||||
|
||||
# TODO: move quiver to PlotRecipes
|
||||
|
||||
+96
-32
@@ -75,7 +75,11 @@ function iter_segments(series::Series)
|
||||
if series[:seriestype] in (:scatter, :scatter3d)
|
||||
return [[i] for i in eachindex(y)]
|
||||
else
|
||||
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
||||
if any(isnan,y)
|
||||
return [iter_segments(y)...]
|
||||
else
|
||||
return [i:(i + 1) for i in firstindex(y):lastindex(y)-1]
|
||||
end
|
||||
end
|
||||
else
|
||||
segs = UnitRange{Int}[]
|
||||
@@ -298,6 +302,11 @@ Base.convert(::Type{Vector{T}}, rng::AbstractRange{S}) where {T<:Real,S<:Real} =
|
||||
|
||||
Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
|
||||
|
||||
# recursively merge kw-dicts, e.g. for merging extra_kwargs / extra_plot_kwargs in plotly)
|
||||
recursive_merge(x::AbstractDict...) = merge(recursive_merge, x...)
|
||||
# if values are not AbstractDicts, take the last definition (as does merge)
|
||||
recursive_merge(x...) = x[end]
|
||||
|
||||
nanpush!(a::AbstractVector, b) = (push!(a, NaN); push!(a, b))
|
||||
nanappend!(a::AbstractVector, b) = (push!(a, NaN); append!(a, b))
|
||||
|
||||
@@ -410,44 +419,46 @@ xlims(sp_idx::Int = 1) = xlims(current(), sp_idx)
|
||||
ylims(sp_idx::Int = 1) = ylims(current(), sp_idx)
|
||||
zlims(sp_idx::Int = 1) = zlims(current(), sp_idx)
|
||||
|
||||
# These functions return an operator for use in `get_clims(::Seres, op)`
|
||||
process_clims(lims::Tuple{<:Number,<:Number}) = (zlims -> ifelse.(isfinite.(lims), lims, zlims)) ∘ ignorenan_extrema
|
||||
process_clims(s::Union{Symbol,Nothing,Missing}) = ignorenan_extrema
|
||||
# don't specialize on ::Function otherwise python functions won't work
|
||||
process_clims(f) = f
|
||||
|
||||
function get_clims(sp::Subplot)
|
||||
function get_clims(sp::Subplot, op=process_clims(sp[:clims]))
|
||||
zmin, zmax = Inf, -Inf
|
||||
for series in series_list(sp)
|
||||
if series[:colorbar_entry]
|
||||
zmin, zmax = _update_clims(zmin, zmax, get_clims(series)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, get_clims(series, op)...)
|
||||
end
|
||||
end
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
end
|
||||
|
||||
function get_clims(sp::Subplot, series::Series)
|
||||
function get_clims(sp::Subplot, series::Series, op=process_clims(sp[:clims]))
|
||||
zmin, zmax = if series[:colorbar_entry]
|
||||
get_clims(sp)
|
||||
get_clims(sp, op)
|
||||
else
|
||||
get_clims(series)
|
||||
end
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
get_clims(series, op)
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
end
|
||||
|
||||
function get_clims(series::Series)
|
||||
"""
|
||||
get_clims(::Series, op=Plots.ignorenan_extrema)
|
||||
|
||||
Finds the limits for the colorbar by taking the "z-values" for the series and passing them into `op`,
|
||||
which must return the tuple `(zmin, zmax)`. The default op is the extrema of the finite
|
||||
values of the input.
|
||||
"""
|
||||
function get_clims(series::Series, op=ignorenan_extrema)
|
||||
zmin, zmax = Inf, -Inf
|
||||
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface)
|
||||
z_colored_series = (:contour, :contour3d, :heatmap, :histogram2d, :surface, :hexbin)
|
||||
for vals in (series[:seriestype] in z_colored_series ? series[:z] : nothing, series[:line_z], series[:marker_z], series[:fill_z])
|
||||
if (typeof(vals) <: AbstractSurface) && (eltype(vals.surf) <: Union{Missing, Real})
|
||||
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals.surf)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, op(vals.surf)...)
|
||||
elseif (vals !== nothing) && (eltype(vals) <: Union{Missing, Real})
|
||||
zmin, zmax = _update_clims(zmin, zmax, ignorenan_extrema(vals)...)
|
||||
zmin, zmax = _update_clims(zmin, zmax, op(vals)...)
|
||||
end
|
||||
end
|
||||
return zmin <= zmax ? (zmin, zmax) : (NaN, NaN)
|
||||
@@ -481,7 +492,7 @@ end
|
||||
hascolorbar(series::Series) = colorbar_style(series) !== nothing
|
||||
hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp))
|
||||
|
||||
iscontour(series::Series) = series[:seriestype] == :contour
|
||||
iscontour(series::Series) = series[:seriestype] in (:contour, :contour3d)
|
||||
isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing
|
||||
|
||||
function contour_levels(series::Series, clims)
|
||||
@@ -587,7 +598,28 @@ function has_attribute_segments(series::Series)
|
||||
end
|
||||
series[:seriestype] == :shape && return false
|
||||
# ... else we check relevant attributes if they have multiple inputs
|
||||
return any((typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1) for attr in [:seriescolor, :seriesalpha, :linecolor, :linealpha, :linewidth, :linestyle, :fillcolor, :fillalpha, :markercolor, :markeralpha, :markerstrokecolor, :markerstrokealpha]) || any(typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z))
|
||||
return any(
|
||||
(typeof(series[attr]) <: AbstractVector && length(series[attr]) > 1)
|
||||
for
|
||||
attr in [
|
||||
:seriescolor,
|
||||
:seriesalpha,
|
||||
:linecolor,
|
||||
:linealpha,
|
||||
:linewidth,
|
||||
:linestyle,
|
||||
:fillcolor,
|
||||
:fillalpha,
|
||||
:markercolor,
|
||||
:markeralpha,
|
||||
:markersize,
|
||||
:markerstrokecolor,
|
||||
:markerstrokealpha,
|
||||
:markerstrokewidth,
|
||||
]
|
||||
) || any(
|
||||
typeof(series[attr]) <: AbstractArray for attr in (:line_z, :fill_z, :marker_z)
|
||||
)
|
||||
end
|
||||
|
||||
function get_aspect_ratio(sp)
|
||||
@@ -603,6 +635,17 @@ function get_aspect_ratio(sp)
|
||||
return aspect_ratio
|
||||
end
|
||||
|
||||
get_size(kw) = get(kw, :size, default(:size))
|
||||
get_size(plt::Plot) = get_size(plt.attr)
|
||||
get_size(sp::Subplot) = get_size(sp.plt)
|
||||
get_size(series::Series) = get_size(series.plotattributes[:subplot])
|
||||
|
||||
get_thickness_scaling(kw) = get(kw, :thickness_scaling, default(:thickness_scaling))
|
||||
get_thickness_scaling(plt::Plot) = get_thickness_scaling(plt.attr)
|
||||
get_thickness_scaling(sp::Subplot) = get_thickness_scaling(sp.plt)
|
||||
get_thickness_scaling(series::Series) =
|
||||
get_thickness_scaling(series.plotattributes[:subplot])
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
makekw(; kw...) = KW(kw)
|
||||
@@ -945,7 +988,7 @@ px2inch(px::Real) = float(px / PX_PER_INCH)
|
||||
inch2mm(inches::Real) = float(inches * MM_PER_INCH)
|
||||
mm2inch(mm::Real) = float(mm / MM_PER_INCH)
|
||||
px2mm(px::Real) = float(px * MM_PER_PX)
|
||||
mm2px(mm::Real) = float(px / MM_PER_PX)
|
||||
mm2px(mm::Real) = float(mm / MM_PER_PX)
|
||||
|
||||
|
||||
"Smallest x in plot"
|
||||
@@ -1036,10 +1079,21 @@ end
|
||||
function straightline_data(series, expansion_factor = 1)
|
||||
sp = series[:subplot]
|
||||
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
|
||||
x, y = series[:x], series[:y]
|
||||
|
||||
# handle axes scales
|
||||
xscale = sp[:xaxis][:scale]
|
||||
xf = RecipesPipeline.scale_func(xscale)
|
||||
xinvf = RecipesPipeline.inverse_scale_func(xscale)
|
||||
yscale = sp[:yaxis][:scale]
|
||||
yf = RecipesPipeline.scale_func(yscale)
|
||||
yinvf = RecipesPipeline.inverse_scale_func(yscale)
|
||||
|
||||
xl, yl = xf.(xl), yf.(yl)
|
||||
x, y = xf.(series[:x]), yf.(series[:y])
|
||||
n = length(x)
|
||||
if n == 2
|
||||
return straightline_data(xl, yl, x, y, expansion_factor)
|
||||
|
||||
xdata, ydata = if n == 2
|
||||
straightline_data(xl, yl, x, y, expansion_factor)
|
||||
else
|
||||
k, r = divrem(n, 3)
|
||||
if r == 0
|
||||
@@ -1048,11 +1102,13 @@ function straightline_data(series, expansion_factor = 1)
|
||||
inds = (3 * i - 2):(3 * i - 1)
|
||||
xdata[inds], ydata[inds] = straightline_data(xl, yl, x[inds], y[inds], expansion_factor)
|
||||
end
|
||||
return xdata, ydata
|
||||
xdata, ydata
|
||||
else
|
||||
error("Misformed data. `straightline_data` either accepts vectors of length 2 or 3k. The provided series has length $n")
|
||||
end
|
||||
end
|
||||
|
||||
return xinvf.(xdata), yinvf.(ydata)
|
||||
end
|
||||
|
||||
function straightline_data(xl, yl, x, y, expansion_factor = 1)
|
||||
@@ -1084,20 +1140,28 @@ end
|
||||
function shape_data(series, expansion_factor = 1)
|
||||
sp = series[:subplot]
|
||||
xl, yl = isvertical(series) ? (xlims(sp), ylims(sp)) : (ylims(sp), xlims(sp))
|
||||
|
||||
# handle axes scales
|
||||
xscale = sp[:xaxis][:scale]
|
||||
xf = RecipesPipeline.scale_func(xscale)
|
||||
xinvf = RecipesPipeline.inverse_scale_func(xscale)
|
||||
yscale = sp[:yaxis][:scale]
|
||||
yf = RecipesPipeline.scale_func(yscale)
|
||||
yinvf = RecipesPipeline.inverse_scale_func(yscale)
|
||||
|
||||
x, y = copy(series[:x]), copy(series[:y])
|
||||
factor = 100
|
||||
for i in eachindex(x)
|
||||
if x[i] == -Inf
|
||||
x[i] = xl[1] - expansion_factor * (xl[2] - xl[1])
|
||||
x[i] = xinvf(xf(xl[1]) - expansion_factor * (xf(xl[2]) - xf(xl[1])))
|
||||
elseif x[i] == Inf
|
||||
x[i] = xl[2] + expansion_factor * (xl[2] - xl[1])
|
||||
x[i] = xinvf(xf(xl[2]) + expansion_factor * (xf(xl[2]) - xf(xl[1])))
|
||||
end
|
||||
end
|
||||
for i in eachindex(y)
|
||||
if y[i] == -Inf
|
||||
y[i] = yl[1] - expansion_factor * (yl[2] - yl[1])
|
||||
y[i] = yinvf(yf(yl[1]) - expansion_factor * (yf(yl[2]) - yf(yl[1])))
|
||||
elseif y[i] == Inf
|
||||
y[i] = yl[2] + expansion_factor * (yl[2] - yl[1])
|
||||
y[i] = yinvf(yf(yl[2]) + expansion_factor * (yf(yl[2]) - yf(yl[1])))
|
||||
end
|
||||
end
|
||||
return x, y
|
||||
|
||||
@@ -9,6 +9,7 @@ using LibGit2
|
||||
using GeometryTypes
|
||||
using Dates
|
||||
|
||||
include("test_axes.jl")
|
||||
include("test_hdf5plots.jl")
|
||||
include("test_pgfplotsx.jl")
|
||||
|
||||
@@ -178,4 +179,9 @@ end
|
||||
@test isequal(collect(zip(Plots.unzip(z)...)), z)
|
||||
@test isequal(collect(zip(Plots.unzip(GeometryTypes.Point.(z))...)), z)
|
||||
end
|
||||
op1 = Plots.process_clims((1.0, 2.0))
|
||||
op2 = Plots.process_clims((1, 2.0))
|
||||
data = randn(100, 100)
|
||||
@test op1(data) == op2(data)
|
||||
@test Plots.process_clims(nothing) == Plots.process_clims(missing) == Plots.process_clims(:auto)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Plots, Test
|
||||
|
||||
@testset "Showaxis" begin
|
||||
for value in Plots._allShowaxisArgs
|
||||
@test plot(1:5, showaxis = value)[1][:yaxis][:showaxis] isa Bool
|
||||
end
|
||||
@test plot(1:5, showaxis = :y)[1][:yaxis][:showaxis] == true
|
||||
@test plot(1:5, showaxis = :y)[1][:xaxis][:showaxis] == false
|
||||
end
|
||||
|
||||
@testset "Magic axis" begin
|
||||
@test plot(1, axis=nothing)[1][:xaxis][:ticks] == []
|
||||
@test plot(1, axis=nothing)[1][:yaxis][:ticks] == []
|
||||
end # testset
|
||||
@@ -326,3 +326,23 @@ end
|
||||
# end
|
||||
end # testset
|
||||
end # testset
|
||||
|
||||
@testset "Extra kwargs" begin
|
||||
pl = plot(1:5, test = "me")
|
||||
@test pl[1][1].plotattributes[:extra_kwargs][:test] == "me"
|
||||
pl = plot(1:5, test = "me", extra_kwargs = :subplot)
|
||||
@test pl[1].attr[:extra_kwargs][:test] == "me"
|
||||
pl = plot(1:5, test = "me", extra_kwargs = :plot)
|
||||
@test pl.attr[:extra_plot_kwargs][:test] == "me"
|
||||
pl = plot(1:5, extra_kwargs = Dict(:plot => Dict(:test => "me"), :series => Dict(:and => "me too")))
|
||||
@test pl.attr[:extra_plot_kwargs][:test] == "me"
|
||||
@test pl[1][1].plotattributes[:extra_kwargs][:and] == "me too"
|
||||
pl = plot(
|
||||
plot(1:5, title="Line"),
|
||||
scatter(1:5, title="Scatter", extra_kwargs=Dict(:subplot=>Dict("axis line shift" => "10pt")))
|
||||
)
|
||||
Plots._update_plot_object(pl)
|
||||
axes = Plots.pgfx_axes(pl.o)
|
||||
@test !haskey(axes[1].options.dict, "axis line shift")
|
||||
@test haskey(axes[2].options.dict, "axis line shift")
|
||||
end # testset
|
||||
|
||||
Reference in New Issue
Block a user