Compare commits

..

83 Commits

Author SHA1 Message Date
Simon Christ 0485b1313a bump version [skip ci] 2020-05-29 15:16:15 +02:00
Daniel Schwabeneder f0f28086a9 Merge pull request #2740 from daschw/vline
fix infinite objects with log scale
2020-05-29 10:50:04 +02:00
Daniel Schwabeneder 580ac8a9d1 fix infinite objects with log scale 2020-05-29 09:42:44 +02:00
Daniel Schwabeneder 84fc6b0be0 Merge pull request #2739 from mileslucas/patch-1
fix type restriction in process_clims
2020-05-28 08:37:13 +02:00
Miles Lucas de81220c01 fix namespace 2020-05-27 12:16:20 -10:00
Miles Lucas ee1f948448 add process_clims tests 2020-05-27 12:00:53 -10:00
Miles Lucas 995c7d349e fix type restriction in process_clims 2020-05-27 11:55:49 -10:00
Simon Christ 4389160a6a bumb version [skip ci] 2020-05-27 15:23:48 +02:00
Simon Christ 8c6295658b fix showaxis fix (#2737)
* also replace axis syms

* process showaxis

* fix axis keyword
2020-05-27 15:23:02 +02:00
Simon Christ a270e342b7 bump version [skip ci] 2020-05-26 20:41:45 +02:00
Simon Christ 42e2266530 Fix showaxis (#2733)
* also replace axis syms

* include test_axes [skip ci]

* Create test_axes.jl

* process showaxis
2020-05-26 20:40:44 +02:00
Cornelius-G 02e6d729c1 add attribute fillalpha to contourf seriestype for pyplot backend (#2732) 2020-05-26 18:37:58 +02:00
Tim Holy baac9a0578 Remove explicit Revise.track from atsign-require blocks (#2734)
* Remove explicit Revise.track from atsign-require blocks

Since Revise 2.4, it has no longer been necessary to explicitly call
Revise.track, as Revise handles this internally.

Also related: https://github.com/timholy/Revise.jl/pull/487,
which checks to see whether Revise.track was called via atsign-require
and if so return without doing anything.

* Bump Requires [compat] to 1
2020-05-26 18:37:13 +02:00
Simon Christ b73dd46521 bump version [skip ci] 2020-05-25 15:01:42 +02:00
isentropic 7bbb2070a7 pyplot colorbar fixes (#2722)
* pyplot colorbar fixes

* pyplot colorbar fixes

* pyplot: sligtly reworked colorbars

* pyplot 3d color bar fixes

* pyplot 3d color bar fixes
2020-05-25 15:00:56 +02:00
Simon Christ 8859518f2d update compat bounds (#2727) 2020-05-25 10:05:33 +02:00
Simon Christ 7f063c71b5 bump version [skip ci] 2020-05-21 12:35:16 +02:00
hhaensel 1e9691a7c0 Add support for mathjax (latex) and extra_plot_kwargs in plotly backend (#2719)
* support mathjax header in plotly backend

* support extra_plot_kwargs in plotly backend

* correct local file parameter to `file:///`

* corrections proposed by @BeastyBlacksmith

* include extra_kwargs for subplots

* don't merge subplot extra_kwargs

Co-authored-by: Helmut Haensel <M136270@eu.merckgroup.com>
Co-authored-by: Simon Christ <SimonChrist@gmx.de>
2020-05-21 12:32:25 +02:00
Simon Christ e5269bcf95 bump version [skip ci] 2020-05-20 15:56:25 +02:00
Simon Christ fdd76a6ca1 Update bug.md 2020-05-20 15:55:52 +02:00
Simon Christ d19525c269 improve title- and legendlocation (#2718)
* improve titlelocation

* fix default case

* improve legend position
2020-05-20 14:55:19 +02:00
Simon Christ 593331dec2 change default alignment in legends (#2714) 2020-05-19 21:20:14 +02:00
Simon Christ b780d90097 minor bump [skip ci] 2020-05-19 13:04:49 +02:00
Simon Christ 2f9ce790e4 deprecate pgfplots (#2711)
* deprecate pgfplots

* Update backends.jl

* Update backends.jl

* Rename src/backends/pgfplots.jl to src/backends/deprecated/pgfplots.jl

* Update init.jl
2020-05-19 13:03:54 +02:00
Simon Christ d8f4519b0c bump version [skip ci] 2020-05-17 10:29:13 +02:00
Simon Christ 702e41f55d add all guide_positions (#2710)
* add all guide_positions

* remove show
2020-05-17 10:28:21 +02:00
Simon Christ 682ac29fcd fix clims (#2709) 2020-05-16 20:10:39 +02:00
Simon Christ c6ce23d0af bump version [skip ci] 2020-05-14 14:45:00 +02:00
Daniel Schwabeneder 9ae7d2dd9d Merge pull request #2700 from daschw/pgfx-colorbar
pgfplotsx colorbar improvements
2020-05-14 14:17:41 +02:00
isentropic 6ec05628d5 python depthshade (#2703)
* python depthshade

* python depthshade
2020-05-14 12:26:18 +02:00
Daniel Schwabeneder f26ebdc2f1 remove unused color strings 2020-05-13 17:21:18 +02:00
Daniel Schwabeneder c97255fc08 don't make colorbars thinner 2020-05-13 17:03:52 +02:00
Daniel Schwabeneder 9d1ede016b make colorbars thinner 2020-05-13 17:03:52 +02:00
Daniel Schwabeneder 7eb8f2452c colorbar positions :top, :bottom and :left and colorbar tickfont fixes 2020-05-13 17:03:52 +02:00
Daniel Schwabeneder 0a6e691222 allow disabling the colorbar in pgfplotsx 2020-05-13 17:03:52 +02:00
jamblejoe 238aca6a78 added description for argument legendtitle (#2697) 2020-05-12 18:32:21 +02:00
Simon Christ 1f039b3adc bump version [skip ci] 2020-05-11 16:52:42 +02:00
Simon Christ 219465d599 fix contours (#2692)
* fix 2d-contour

* fix filled contours (colorbar is off)

* activate fixed examples
2020-05-11 16:52:00 +02:00
Simon Christ 1963cee94a fix it again (#2694) 2020-05-11 16:51:38 +02:00
Simon Christ ae43e05f6f bump version [skip ci] 2020-05-09 13:10:32 +02:00
Simon Christ 5cd2ba7296 Delete tmpplotsave.hdf5 2020-05-09 13:09:53 +02:00
isentropic 4a00018f25 pyplot hexbin (#2679)
* pyplot hexbin

* pyplot hexbin changes
2020-05-09 13:07:32 +02:00
Simon Christ 32c725e770 error bars behind in scatterplots (#2677)
* errors behind for :scatter

* fix plots with no seriestype
2020-05-09 13:05:15 +02:00
Daniel Schwabeneder 4e2ee35125 Merge pull request #2684 from daschw/gr-ticklabel
fix numeric gr ticklabels
2020-05-08 10:15:04 +02:00
Daniel Schwabeneder 35b0751714 fix numeric gr ticklabels 2020-05-07 18:17:47 +02:00
Zh 28ebc0ccd8 pyplot hexbin 2020-05-07 03:02:00 +09:00
Simon Christ 3d693d88e0 Change color handling of error recipes (#2675)
* fix iteration of segments

* fix error vector arg detection

* change color handling of recipes
2020-05-06 18:21:54 +02:00
Daniel Schwabeneder 6ddf31d465 Merge pull request #2673 from komi1230/master
Removed arrow3d from gr.jl in backends/
2020-05-05 20:50:40 +02:00
Yusuke Kominami 5c1ea707ca removed unnecessary args 2020-05-06 01:24:20 +09:00
Yusuke Kominami a6669f89a0 removed arrow3d 2020-05-05 23:18:03 +09:00
Simon Christ 2a2d509c36 Version bump
[skip ci]
2020-05-05 10:26:56 +02:00
isentropic fd4efb3f33 PyPlot: z-axis guidefontrotation only works for short labels Fix 2641 (#2667) 2020-05-05 10:26:01 +02:00
isentropic e90ab0b898 PyPlot fix contour labels (#2668) 2020-05-05 10:25:12 +02:00
Simon Christ 44367c54da fix quiver (#2670) 2020-05-05 10:24:15 +02:00
Daniel Schwabeneder 3273a65889 Merge pull request #2657 from mileslucas/climsfunc
allow passing a function to `clims`
2020-05-05 08:18:07 +02:00
Miles Lucas 0aa606d835 fix typo in get_clims function docstring 2020-05-04 11:05:53 -10:00
Simon Christ 40848e7432 fix error recipes (#2665)
* fix scatterbins

* fix zerror
2020-05-04 18:16:29 +02:00
Michael Krabbe Borregaard fe4cc4d58c update patch version 2020-05-04 18:12:20 +02:00
Daniel Schwabeneder 56f90ffaf3 Merge pull request #2663 from dietercastel/webm
Added webm support for animations.
2020-05-03 19:28:49 +02:00
Daniel Schwabeneder dfb556339f Merge pull request #2662 from daschw/plotarea
GR size fixes
2020-05-03 15:54:56 +02:00
Daniel Schwabeneder 61f5a7f437 fix extra_kwargs docs string 2020-05-03 15:39:51 +02:00
Daniel Schwabeneder 3be9b8d076 fix outer legend font size 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder 2a138dee40 fix get_size and get_thickness_scaling for series 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder 712ef74b81 remove const _gr_plot_size, _gr_point_mult and _gr_thickness_scaling 2020-05-03 15:37:12 +02:00
Daniel Schwabeneder ba8ca424cf remove gloabal viewport_plotarea in gr 2020-05-03 15:37:12 +02:00
Dieter Castel c6784a779b Added webm support for animations. 2020-05-03 15:31:55 +02:00
Simon Christ d667cb7e57 update documentation of extra_kwargs 2020-05-03 15:10:34 +02:00
Miles Lucas 10a5c2ed1d fix bug with Tuple clims and fix typos 2020-05-01 00:10:27 -10:00
Miles Lucas 8cce78c890 fix typos 2020-04-30 23:38:52 -10:00
Miles Lucas 294ade8aad refactor get_clims calls to use operators 2020-04-30 23:32:30 -10:00
Miles Lucas a59e8411c9 update clims arg description 2020-04-30 22:30:03 -10:00
Daniel Schwabeneder d973f437ef Merge pull request #2653 from daschw/segments
make segments for vectors of markersize and markerstrokewidth
2020-04-30 14:05:45 +02:00
Josef Heinen d5ce2c1431 Merge remote-tracking branch 'upstream/master' 2020-04-30 13:25:06 +02:00
Josef Heinen 834e2a99e3 add actual GR version 2020-04-30 13:18:32 +02:00
Daniel Schwabeneder f8e9e33347 Merge pull request #2650 from daschw/pyplot
pyplot legend marker fixes
2020-04-30 13:17:53 +02:00
Daniel Schwabeneder a0c7781296 make segments for vectors of markersize and markerstrokewidth 2020-04-30 13:16:33 +02:00
Daniel Schwabeneder 2ea998983d fix legend marker for vector of markersizes [skip ci] 2020-04-30 10:04:04 +02:00
Daniel Schwabeneder e44b220b84 fix legend marker linewidth for steppre and steppost [skip ci] 2020-04-30 10:03:21 +02:00
Daniel Schwabeneder 756cccb114 remove lines in legend markers for scatter plots in pyplot [skip ci] 2020-04-30 09:46:13 +02:00
Simon Christ af9982b804 minor bump [skip ci] 2020-04-29 11:47:54 +02:00
Simon Christ 1b946a18d2 passing of extra keywords to pgfplotsx (#2200)
* transfer commit

* extra_kwargs gets populated

* make extra_kwargs a series kw.

* turn extra_kwargs into Dict of Dicts

* pass to pgfplotsx-backend

* add test

* change to dict

* it even works

* cleanup

* undo pgfplots changes

* all of them

* fix tests

* add pgfplotsx tests and special handling of :add

Co-authored-by: Simon Christ <Simon.Christ@mpikg.mpg.de>
2020-04-29 11:43:57 +02:00
Simon Christ a397bfd549 bump version [skip ci]
@JuliaRegistrator register
2020-04-29 11:33:36 +02:00
isentropic d276ac6857 pyplot: legend marker scales independently (#2616)
* pyplot: legend marker scales independently

* pyplot: marker size scales correctly

* pyplot: marker size scales correctly

* pyplot: marker size scales correctly

* pyplot: lw in legend scales with legendfont

* pyplot: legendmarker size 0.8
2020-04-29 11:32:22 +02:00
21 changed files with 645 additions and 355 deletions
+2 -2
View File
@@ -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
View File
@@ -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"
+1
View File
@@ -108,6 +108,7 @@ export
gif,
mov,
mp4,
webm,
animate,
@animate,
@gif,
+4 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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)
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+8 -3
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+6
View File
@@ -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
+14
View File
@@ -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
+20
View File
@@ -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