Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6bebe1ce2 | |||
| e2c387894f | |||
| bf85afe9d6 | |||
| 217e67fb7f | |||
| 3053bb4cc2 | |||
| 8dcff1f73d | |||
| c73a5aaabc | |||
| 806d4671ce | |||
| c4a64351ca | |||
| 345bceb526 | |||
| 5673ced5d7 | |||
| a929903a63 | |||
| b9cf8c3928 | |||
| 9b573dce49 | |||
| c2bb17cece | |||
| 7e122bdfea | |||
| 1ee999af33 | |||
| 381f14b657 | |||
| 3fec5ae1cf | |||
| b154a1a3e4 | |||
| cef0a55870 | |||
| 61e80e96cf | |||
| 0db321aecc | |||
| 8b7f87506a | |||
| f9f6e0ff57 | |||
| 6f36d0998f | |||
| 943bdca05e | |||
| bece65e922 | |||
| 2fb315af0e | |||
| 849c2911a7 | |||
| fa720d6ad4 | |||
| 1ab681f509 | |||
| 0d776fd09d | |||
| 45e33f5b6f | |||
| 1c4910f90e | |||
| 2f4eb7b558 | |||
| 02ca049bc6 | |||
| ff7235e9b8 | |||
| 376fae0d79 | |||
| d036794576 |
@@ -23,8 +23,7 @@ jobs:
|
||||
version: # NOTE: the versions below should match those in your botconfig
|
||||
- '1.3'
|
||||
- '1.4'
|
||||
- '1.5.0-rc1'
|
||||
- 'nightly'
|
||||
- '1.5'
|
||||
os: # NOTE: should match the os setting of your botconfig
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
name = "Plots"
|
||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||
author = ["Tom Breloff (@tbreloff)"]
|
||||
version = "1.5.3"
|
||||
version = "1.6.0"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
@@ -33,9 +33,9 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
|
||||
[compat]
|
||||
Contour = "0.5"
|
||||
FFMPEG = "0.2, 0.3"
|
||||
FFMPEG = "0.2, 0.3, 0.4"
|
||||
FixedPointNumbers = "0.6, 0.7, 0.8"
|
||||
GR = "0.46, 0.47, 0.48, 0.49, 0.50"
|
||||
GR = "0.46, 0.47, 0.48, 0.49, 0.50, 0.51"
|
||||
GeometryBasics = "0.2"
|
||||
GeometryTypes = "0.7, 0.8"
|
||||
JSON = "0.21, 1"
|
||||
@@ -45,7 +45,7 @@ PGFPlotsX = "1.2.0"
|
||||
PlotThemes = "2"
|
||||
PlotUtils = "1"
|
||||
RecipesBase = "1"
|
||||
RecipesPipeline = "0.1.7"
|
||||
RecipesPipeline = "0.1.12"
|
||||
Reexport = "0.2"
|
||||
Requires = "1"
|
||||
Showoff = "0.3.1"
|
||||
|
||||
+3
-3
@@ -90,15 +90,15 @@ function buildanimation(anim::Animation, fn::AbstractString,
|
||||
if variable_palette
|
||||
# generate a colorpalette for each frame for highest quality, but larger filesize
|
||||
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1"
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -lavfi "$palette" -loop $loop -y $fn`)
|
||||
else
|
||||
# generate a colorpalette first so ffmpeg does not have to guess it
|
||||
ffmpeg_exe(`-v $verbose_level -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
|
||||
# then apply the palette to get better results
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -loop $loop -y $fn`)
|
||||
end
|
||||
else
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
|
||||
ffmpeg_exe(`-v $verbose_level -framerate $framerate -i $(animdir)/%06d.png -loop $loop -y $fn`)
|
||||
end
|
||||
|
||||
show_msg && @info("Saved animation to ", fn)
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ const _arg_desc = KW(
|
||||
:foreground_color => "Color Type. Base color for all foregrounds.",
|
||||
:size => "NTuple{2,Int}. (width_px, height_px) of the whole Plot",
|
||||
:pos => "NTuple{2,Int}. (left_px, top_px) position of the GUI window (note: currently unimplemented)",
|
||||
:window_title => "String. Title of the window.",
|
||||
:window_title => "String. Title of the standalone gui-window.",
|
||||
:show => "Bool. Should this command open/refresh a GUI/display? This allows displaying in scripts or functions without explicitly calling `display`",
|
||||
:layout => "Integer (number of subplots), NTuple{2,Integer} (grid dimensions), AbstractLayout (for example `grid(2,2)`), or the return from the `@layout` macro. This builds the layout of subplots.",
|
||||
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
|
||||
|
||||
+30
-9
@@ -38,7 +38,7 @@ const _axesAliases = Dict{Symbol,Symbol}(
|
||||
)
|
||||
|
||||
const _3dTypes = [
|
||||
:path3d, :scatter3d, :surface, :wireframe, :contour3d, :volume
|
||||
:path3d, :scatter3d, :surface, :wireframe, :contour3d, :volume, :mesh3d
|
||||
]
|
||||
const _allTypes = vcat([
|
||||
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
||||
@@ -288,12 +288,20 @@ 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.
|
||||
:connections => nothing, # tuple of arrays to specifiy connectivity of a 3d mesh
|
||||
:extra_kwargs => Dict()
|
||||
)
|
||||
|
||||
|
||||
const _plot_defaults = KW(
|
||||
:plot_title => "",
|
||||
:plot_titlefontsize => 16,
|
||||
:plot_title_location => :center, # also :left or :right
|
||||
:plot_titlefontfamily => :match,
|
||||
:plot_titlefonthalign => :hcenter,
|
||||
:plot_titlefontvalign => :vcenter,
|
||||
:plot_titlefontrotation => 0.0,
|
||||
:plot_titlefontcolor => :match,
|
||||
:background_color => colorant"white", # default for all backgrounds,
|
||||
:background_color_outside => :match, # background outside grid,
|
||||
:foreground_color => :auto, # default for all foregrounds, and title color,
|
||||
@@ -360,10 +368,18 @@ const _subplot_defaults = KW(
|
||||
:right_margin => :match,
|
||||
:bottom_margin => :match,
|
||||
:subplot_index => -1,
|
||||
:colorbar_title => "",
|
||||
:framestyle => :axes,
|
||||
:camera => (30,30),
|
||||
:extra_kwargs => Dict()
|
||||
:colorbar_title => "",
|
||||
:colorbar_titlefontsize => 10,
|
||||
:colorbar_title_location => :center, # also :left or :right
|
||||
:colorbar_fontfamily => :match,
|
||||
:colorbar_titlefontfamily => :match,
|
||||
:colorbar_titlefonthalign => :hcenter,
|
||||
:colorbar_titlefontvalign => :vcenter,
|
||||
:colorbar_titlefontrotation => 0.0,
|
||||
:colorbar_titlefontcolor => :match,
|
||||
:framestyle => :axes,
|
||||
:camera => (30,30),
|
||||
:extra_kwargs => Dict()
|
||||
)
|
||||
|
||||
const _axis_defaults = KW(
|
||||
@@ -468,7 +484,7 @@ const _subplot_args = sort(union(collect(keys(_subplot_defaults))))
|
||||
const _plot_args = sort(union(collect(keys(_plot_defaults))))
|
||||
|
||||
const _magic_axis_args = [:axis, :tickfont, :guidefont, :grid, :minorgrid]
|
||||
const _magic_subplot_args = [:titlefont, :legendfont, :legendtitlefont, ]
|
||||
const _magic_subplot_args = [:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont]
|
||||
const _magic_series_args = [:line, :marker, :fill]
|
||||
|
||||
const _all_axis_args = sort(union([_axis_args; _magic_axis_args]))
|
||||
@@ -1048,7 +1064,7 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW)
|
||||
end
|
||||
|
||||
# fonts
|
||||
for fontname in (:titlefont, :legendfont, :legendtitlefont)
|
||||
for fontname in (:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont)
|
||||
args = RecipesPipeline.pop_kw!(plotattributes, fontname, ())
|
||||
for arg in wraptuple(args)
|
||||
processFontArg!(plotattributes, fontname, arg)
|
||||
@@ -1285,11 +1301,16 @@ const _match_map = KW(
|
||||
:right_margin => :margin,
|
||||
:bottom_margin => :margin,
|
||||
:titlefontfamily => :fontfamily_subplot,
|
||||
:legendfontfamily => :fontfamily_subplot,
|
||||
:legendtitlefontfamily => :fontfamily_subplot,
|
||||
:titlefontcolor => :foreground_color_subplot,
|
||||
:legendfontfamily => :fontfamily_subplot,
|
||||
:legendfontcolor => :foreground_color_subplot,
|
||||
:legendtitlefontfamily => :fontfamily_subplot,
|
||||
:legendtitlefontcolor => :foreground_color_subplot,
|
||||
:colorbar_fontfamily => :fontfamily_subplot,
|
||||
:colorbar_titlefontfamily => :fontfamily_subplot,
|
||||
:colorbar_titlefontcolor => :foreground_color_subplot,
|
||||
:plot_titlefontfamily => :fontfamily,
|
||||
:plot_titlefontcolor => :foreground_color,
|
||||
:tickfontcolor => :foreground_color_text,
|
||||
:guidefontcolor => :foreground_color_guide,
|
||||
)
|
||||
|
||||
@@ -429,6 +429,7 @@ const _plotly_seriestype = [
|
||||
:shape,
|
||||
:scattergl,
|
||||
:straightline,
|
||||
:mesh3d
|
||||
]
|
||||
const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot]
|
||||
const _plotly_marker = [
|
||||
|
||||
+43
-25
@@ -349,11 +349,13 @@ function gr_draw_markers(
|
||||
|
||||
shapes = series[:markershape]
|
||||
if shapes != :none
|
||||
for i in eachindex(x)
|
||||
for (i, rng) in enumerate(iter_segments(series))
|
||||
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)
|
||||
for j in rng
|
||||
gr_draw_marker(series, _cycle(x, j), _cycle(y, j), clims, i, ms, msw, shape)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -565,6 +567,8 @@ gr_view_xcenter(viewport_plotarea) = 0.5 * (viewport_plotarea[1] + viewport_plot
|
||||
gr_view_ycenter(viewport_plotarea) = 0.5 * (viewport_plotarea[3] + viewport_plotarea[4])
|
||||
|
||||
function gr_legend_pos(sp::Subplot, w, h, viewport_plotarea)
|
||||
legend_leftw, legend_rightw, legend_textw, x_legend_offset = w
|
||||
legend_dy, legendh, y_legend_offset = h
|
||||
s = sp[:legend]
|
||||
typeof(s) <: Symbol || return gr_legend_pos(s, w, h, viewport_plotarea)
|
||||
str = string(s)
|
||||
@@ -579,34 +583,34 @@ function gr_legend_pos(sp::Subplot, w, h, viewport_plotarea)
|
||||
if occursin("right", str)
|
||||
if occursin("outer", str)
|
||||
# As per https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl#L525
|
||||
xpos = viewport_plotarea[2] + 0.11 + ymirror * gr_axis_width(sp, sp[:yaxis])
|
||||
xpos = viewport_plotarea[2] + x_legend_offset + legend_leftw + ymirror * gr_axis_width(sp, sp[:yaxis])
|
||||
else
|
||||
xpos = viewport_plotarea[2] - 0.05 - w
|
||||
xpos = viewport_plotarea[2] - legend_rightw - legend_textw - x_legend_offset
|
||||
end
|
||||
elseif occursin("left", str)
|
||||
if occursin("outer", str)
|
||||
xpos = viewport_plotarea[1] - 0.05 - w - !ymirror * gr_axis_width(sp, sp[:yaxis])
|
||||
xpos = viewport_plotarea[1] - !ymirror * gr_axis_width(sp, sp[:yaxis]) - x_legend_offset * 2 - legend_rightw - legend_textw
|
||||
else
|
||||
xpos = viewport_plotarea[1] + 0.11
|
||||
xpos = viewport_plotarea[1] + legend_leftw + x_legend_offset
|
||||
end
|
||||
else
|
||||
xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 - w/2 +.04 + viewport_plotarea[1]
|
||||
xpos = (viewport_plotarea[2]-viewport_plotarea[1])/2 + viewport_plotarea[1] + legend_leftw - legend_rightw - legend_textw - x_legend_offset * 2
|
||||
end
|
||||
if occursin("top", str)
|
||||
if s == :outertop
|
||||
ypos = viewport_plotarea[4] + 0.02 + h + xmirror * gr_axis_height(sp, sp[:xaxis])
|
||||
ypos = viewport_plotarea[4] + y_legend_offset + legendh + xmirror * gr_axis_height(sp, sp[:xaxis])
|
||||
else
|
||||
ypos = viewport_plotarea[4] - 0.06
|
||||
ypos = viewport_plotarea[4] - y_legend_offset - legend_dy
|
||||
end
|
||||
elseif occursin("bottom", str)
|
||||
if s == :outerbottom
|
||||
ypos = viewport_plotarea[3] - 0.05 - !xmirror * gr_axis_height(sp, sp[:xaxis])
|
||||
ypos = viewport_plotarea[3] - y_legend_offset - legendh - !xmirror * gr_axis_height(sp, sp[:xaxis])
|
||||
else
|
||||
ypos = viewport_plotarea[3] + h + 0.06
|
||||
ypos = viewport_plotarea[3] + legendh + y_legend_offset
|
||||
end
|
||||
else
|
||||
# Adding min y to shift legend pos to correct graph (#2377)
|
||||
ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + h/2 + viewport_plotarea[3]
|
||||
ypos = (viewport_plotarea[4]-viewport_plotarea[3])/2 + legendh/2 + viewport_plotarea[3]
|
||||
end
|
||||
(xpos,ypos)
|
||||
end
|
||||
@@ -1003,7 +1007,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
legendn += 1
|
||||
lab = series[:label]
|
||||
tbx, tby = gr_inqtext(0, 0, string(lab))
|
||||
legendw = max(legendw, tbx[3] - tbx[1])
|
||||
legendw = max(legendw, tbx[3] - tbx[1]) # Holds text width right now
|
||||
end
|
||||
|
||||
GR.setscale(1)
|
||||
@@ -1011,18 +1015,32 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
legend_width_factor = (viewport_plotarea[2] - viewport_plotarea[1]) / 45 # Determines the width of legend box
|
||||
legend_textw = legendw
|
||||
legend_rightw = legend_width_factor
|
||||
legend_leftw = legend_width_factor * 4
|
||||
total_legendw = legend_textw + legend_leftw + legend_rightw
|
||||
|
||||
x_legend_offset = (viewport_plotarea[2] - viewport_plotarea[1]) / 30
|
||||
y_legend_offset = (viewport_plotarea[4] - viewport_plotarea[3]) / 30
|
||||
|
||||
dy = gr_point_mult(sp) * sp[:legendfontsize] * 1.75
|
||||
legendh = dy * legendn
|
||||
leg_str = string(sp[:legend])
|
||||
|
||||
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
|
||||
xmirror = xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||
ymirror = yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
|
||||
|
||||
if occursin("outer", leg_str)
|
||||
if occursin("right", leg_str)
|
||||
viewport_plotarea[2] -= legendw + 0.12
|
||||
viewport_plotarea[2] -= total_legendw + x_legend_offset
|
||||
elseif occursin("left", leg_str)
|
||||
viewport_plotarea[1] += legendw + 0.11
|
||||
viewport_plotarea[1] += total_legendw + x_legend_offset + !ymirror * gr_axis_width(sp, sp[:yaxis])
|
||||
elseif occursin("top", leg_str)
|
||||
viewport_plotarea[4] -= legendh + 0.03
|
||||
viewport_plotarea[4] -= legendh + dy + y_legend_offset
|
||||
elseif occursin("bottom", leg_str)
|
||||
viewport_plotarea[3] += legendh + 0.04
|
||||
viewport_plotarea[3] += legendh + dy + y_legend_offset + !xmirror * gr_axis_height(sp, sp[:xaxis])
|
||||
end
|
||||
end
|
||||
if sp[:legend] == :inline
|
||||
@@ -1840,17 +1858,17 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.selntran(0)
|
||||
GR.setscale(0)
|
||||
gr_set_font(legendfont(sp), sp)
|
||||
w = legendw
|
||||
w = legendw # This is the legend text width
|
||||
n = legendn
|
||||
if w > 0
|
||||
dy = gr_point_mult(sp) * sp[:legendfontsize] * 1.75
|
||||
h = dy*n
|
||||
xpos, ypos = gr_legend_pos(sp, w, h, viewport_plotarea)
|
||||
xpos, ypos = gr_legend_pos(sp, [legend_leftw, legend_rightw, legend_textw, x_legend_offset, y_legend_offset], [dy, h, y_legend_offset], viewport_plotarea) # Passing legend width components instead of legend text width
|
||||
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.fillrect(xpos - legend_leftw, xpos + legend_textw + legend_rightw, ypos + dy, ypos - dy * n) # Allocating white space for actual legend width here
|
||||
gr_set_line(1, :solid, sp[:foreground_color_legend], sp)
|
||||
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
||||
GR.drawrect(xpos - legend_leftw, xpos + legend_textw + legend_rightw, ypos + dy, ypos - dy * n) # Drawing actual legend width here
|
||||
i = 0
|
||||
if sp[:legendtitle] !== nothing
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
||||
@@ -1869,7 +1887,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
if (st == :shape || series[:fillrange] !== nothing) && series[:ribbon] === nothing
|
||||
fc = get_fillcolor(series, clims)
|
||||
gr_set_fill(fc) #, series[:fillalpha])
|
||||
l, r = xpos-0.07, xpos-0.01
|
||||
l, r = xpos - legend_width_factor * 3.5, xpos - legend_width_factor / 2
|
||||
b, t = ypos-0.4dy, ypos+0.4dy
|
||||
x = [l, r, r, l, l]
|
||||
y = [b, b, t, t, b]
|
||||
@@ -1884,9 +1902,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
if st in (:path, :straightline, :path3d)
|
||||
gr_set_transparency(lc, get_linealpha(series))
|
||||
if series[:fillrange] === nothing || series[:ribbon] !== nothing
|
||||
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos, ypos])
|
||||
GR.polyline([xpos - legend_width_factor * 3.5, xpos - legend_width_factor / 2], [ypos, ypos])
|
||||
else
|
||||
GR.polyline([xpos - 0.07, xpos - 0.01], [ypos+0.4dy, ypos+0.4dy])
|
||||
GR.polyline([xpos - legend_width_factor * 3.5, xpos - legend_width_factor / 2], [ypos+0.4dy, ypos+0.4dy])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1899,7 +1917,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
0, 0.8 * sp[:legendfontsize] * msw / 8
|
||||
end
|
||||
gr_draw_markers(
|
||||
series, xpos - 0.035, ypos, clims, s, sw
|
||||
series, xpos - legend_width_factor * 2, ypos, clims, s, sw
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
+23
-32
@@ -83,17 +83,17 @@ function Base.push!(pgfx_plot::PGFPlotsXPlot, item)
|
||||
push!(pgfx_plot.the_plot, item)
|
||||
end
|
||||
|
||||
function pgfx_split_extra_opts(extra)
|
||||
return (get(extra, :add, nothing), filter( x-> first(x) != :add, extra))
|
||||
end
|
||||
function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
if !pgfx_plot.is_created || pgfx_plot.was_shown
|
||||
pgfx_sanitize_plot!(plt)
|
||||
# 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
|
||||
extra_plot, extra_plot_opt = pgfx_split_extra_opts(plt[:extra_plot_kwargs])
|
||||
the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options(extra_plot_opt...))
|
||||
if extra_plot !== nothing
|
||||
extra_plot = wraptuple(extra_plot)
|
||||
push!(the_plot, extra_plot...)
|
||||
end
|
||||
bgc = plt.attr[:background_color_outside] == :match ?
|
||||
@@ -249,13 +249,10 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
else
|
||||
PGFPlotsX.Axis
|
||||
end
|
||||
extra_sp_opt = sp[:extra_kwargs]
|
||||
extra_sp = nothing
|
||||
if haskey(extra_sp_opt, :add)
|
||||
extra_sp = wraptuple(pop!(extra_sp_opt,:add))
|
||||
end
|
||||
extra_sp, extra_sp_opt = pgfx_split_extra_opts(sp[:extra_kwargs])
|
||||
axis = axisf(merge(axis_opt, PGFPlotsX.Options(extra_sp_opt...)))
|
||||
if extra_sp !== nothing
|
||||
extra_sp = wraptuple(extra_sp)
|
||||
push!(axis, extra_sp...)
|
||||
end
|
||||
if sp[:legendtitle] !== nothing
|
||||
@@ -279,11 +276,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
"color" => single_color(opt[:linecolor]),
|
||||
"name path" => string(series_id),
|
||||
)
|
||||
extra_series_opt = series[:extra_kwargs]
|
||||
extra_series = nothing
|
||||
if haskey(extra_series_opt, :add)
|
||||
extra_series = wraptuple(pop!(extra_series_opt,:add))
|
||||
end
|
||||
extra_series, extra_series_opt = pgfx_split_extra_opts(series[:extra_kwargs])
|
||||
series_opt = merge(series_opt, PGFPlotsX.Options(extra_series_opt...))
|
||||
if RecipesPipeline.is3d(series) || st in (:heatmap, :contour)
|
||||
series_func = PGFPlotsX.Plot3
|
||||
@@ -344,9 +337,8 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
end
|
||||
# add fillrange
|
||||
if sf !== nothing &&
|
||||
!isfilledcontour(series) &&
|
||||
series[:ribbon] === nothing
|
||||
if sf isa Number || sf isa AVec
|
||||
!isfilledcontour(series)
|
||||
if sf isa Number || sf isa AVec
|
||||
pgfx_fillrange_series!(
|
||||
axis,
|
||||
series,
|
||||
@@ -355,6 +347,17 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
_cycle(sf, rng),
|
||||
rng,
|
||||
)
|
||||
elseif sf isa Tuple && series[:ribbon] !== nothing
|
||||
for sfi in sf
|
||||
pgfx_fillrange_series!(
|
||||
axis,
|
||||
series,
|
||||
series_func,
|
||||
i,
|
||||
_cycle(sfi, rng),
|
||||
rng,
|
||||
)
|
||||
end
|
||||
end
|
||||
if i == 1 &&
|
||||
sp[:legend] != :none && pgfx_should_add_to_legend(series)
|
||||
@@ -366,6 +369,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
segment_plot =
|
||||
series_func(merge(series_opt, segment_opt), coordinates)
|
||||
if extra_series !== nothing
|
||||
extra_series = wraptuple(extra_series)
|
||||
push!(segment_plot, extra_series...)
|
||||
end
|
||||
push!(axis, segment_plot)
|
||||
@@ -384,17 +388,6 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
),
|
||||
)
|
||||
end
|
||||
# add ribbons?
|
||||
ribbon = series[:ribbon]
|
||||
if ribbon !== nothing
|
||||
pgfx_add_ribbons!(
|
||||
axis,
|
||||
series,
|
||||
segment_plot,
|
||||
series_func,
|
||||
series_index,
|
||||
)
|
||||
end
|
||||
# add to legend?
|
||||
if sp[:legend] != :none
|
||||
leg_entry = if opt[:label] isa AVec
|
||||
@@ -412,9 +405,6 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
||||
push!(axis.contents[end].options, "forget plot" => nothing)
|
||||
else
|
||||
leg_opt = PGFPlotsX.Options()
|
||||
if ribbon !== nothing
|
||||
pgfx_filllegend!(axis.contents[end - 3].options, opt)
|
||||
end
|
||||
legend = PGFPlotsX.LegendEntry(leg_opt, leg_entry, false)
|
||||
push!(axis, legend)
|
||||
end
|
||||
@@ -558,6 +548,7 @@ function pgfx_series_coordinates!(st_val::Val{:surface}, segment_opt, opt, args)
|
||||
"surf" => nothing,
|
||||
"mesh/rows" => length(opt[:x]),
|
||||
"mesh/cols" => length(opt[:y]),
|
||||
"z buffer" => "sort",
|
||||
)
|
||||
return PGFPlotsX.Coordinates(args...)
|
||||
end
|
||||
|
||||
+26
-4
@@ -1,4 +1,3 @@
|
||||
|
||||
# https://plot.ly/javascript/getting-started
|
||||
|
||||
is_subplot_supported(::PlotlyBackend) = true
|
||||
@@ -446,7 +445,7 @@ function plotly_data(series::Series, letter::Symbol, data)
|
||||
data
|
||||
end
|
||||
|
||||
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe)
|
||||
if series[:seriestype] in (:heatmap, :contour, :surface, :wireframe, :mesh3d)
|
||||
plotly_surface_data(series, data)
|
||||
else
|
||||
plotly_data(data)
|
||||
@@ -553,7 +552,7 @@ function plotly_series(plt::Plot, series::Series)
|
||||
plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series)
|
||||
|
||||
elseif st in (:surface, :wireframe)
|
||||
plotattributes_out[:type] = "surface"
|
||||
plotattributes_out[:type] = "surface"
|
||||
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
|
||||
if st == :wireframe
|
||||
plotattributes_out[:hidesurface] = true
|
||||
@@ -572,7 +571,30 @@ function plotly_series(plt::Plot, series::Series)
|
||||
end
|
||||
plotattributes_out[:showscale] = hascolorbar(sp)
|
||||
end
|
||||
|
||||
elseif st == :mesh3d
|
||||
plotattributes_out[:type] = "mesh3d"
|
||||
plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z
|
||||
|
||||
if series[:connections] != nothing
|
||||
if typeof(series[:connections]) <: Tuple{Array,Array,Array}
|
||||
i,j,k = series[:connections]
|
||||
if !(length(i) == length(j) == length(k))
|
||||
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
|
||||
end
|
||||
plotattributes_out[:i] = i
|
||||
plotattributes_out[:j] = j
|
||||
plotattributes_out[:k] = k
|
||||
else
|
||||
throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
|
||||
end
|
||||
end
|
||||
plotattributes_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
|
||||
plotattributes_out[:color] = rgba_string(plot_color(series[:fillcolor], series[:fillalpha]))
|
||||
plotattributes_out[:opacity] = series[:fillalpha]
|
||||
if series[:fill_z] !== nothing
|
||||
plotattributes_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
|
||||
end
|
||||
plotattributes_out[:showscale] = hascolorbar(sp)
|
||||
else
|
||||
@warn("Plotly: seriestype $st isn't supported.")
|
||||
return KW()
|
||||
|
||||
+27
-14
@@ -23,6 +23,7 @@ pynp."seterr"(invalid="ignore")
|
||||
pytransforms = PyPlot.pyimport("matplotlib.transforms")
|
||||
pycollections = PyPlot.pyimport("matplotlib.collections")
|
||||
pyart3d = PyPlot.art3D
|
||||
pyrcparams = PyPlot.PyDict(PyPlot.matplotlib."rcParams")
|
||||
|
||||
# "support" matplotlib v1.5
|
||||
set_facecolor_sym = if PyPlot.version < v"2"
|
||||
@@ -276,7 +277,6 @@ end
|
||||
function py_bbox_axis(ax, letter)
|
||||
ticks = py_bbox_ticks(ax, letter)
|
||||
labels = py_bbox_axislabel(ax, letter)
|
||||
# letter == "x" && @show ticks labels ticks+labels
|
||||
ticks + labels
|
||||
end
|
||||
|
||||
@@ -728,8 +728,10 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st == :image
|
||||
# @show typeof(z)
|
||||
xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
|
||||
xmin, xmax = ignorenan_extrema(series[:x])
|
||||
ymin, ymax = ignorenan_extrema(series[:y])
|
||||
dx = (xmax - xmin) / (length(series[:x]) - 1) / 2
|
||||
dy = (ymax - ymin) / (length(series[:y]) - 1) / 2
|
||||
img = Array(transpose_z(series, z.surf))
|
||||
z = if eltype(img) <: Colors.AbstractGray
|
||||
float(img)
|
||||
@@ -743,7 +745,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
cmap = py_colormap(cgrad(plot_color([:black, :white]))),
|
||||
vmin = 0.0,
|
||||
vmax = 1.0,
|
||||
extent = (xmin-0.5, xmax+0.5, ymax+0.5, ymin-0.5)
|
||||
extent = (xmin - dx, xmax + dx, ymax + dy, ymin - dy)
|
||||
)
|
||||
push!(handles, handle)
|
||||
|
||||
@@ -840,7 +842,9 @@ function py_set_lims(ax, sp::Subplot, axis::Axis)
|
||||
getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto)
|
||||
end
|
||||
|
||||
function py_set_ticks(ax, ticks, letter)
|
||||
py_surround_latextext(latexstring, env) = PyPlot.LaTeXStrings.latexstring(env, "{",latexstring[2:end-1],"}")
|
||||
|
||||
function py_set_ticks(ax, ticks, letter, env)
|
||||
ticks == :auto && return
|
||||
axis = getproperty(ax, Symbol(letter,"axis"))
|
||||
if ticks == :none || ticks === nothing || ticks == false
|
||||
@@ -857,7 +861,8 @@ function py_set_ticks(ax, ticks, letter)
|
||||
axis."set_ticks"(ticks)
|
||||
elseif ttype == :ticks_and_labels
|
||||
axis."set_ticks"(ticks[1])
|
||||
axis."set_ticklabels"(ticks[2])
|
||||
tick_labels = [py_surround_latextext(ticklabel, env) for ticklabel in ticks[2]]
|
||||
axis."set_ticklabels"(tick_labels)
|
||||
else
|
||||
error("Invalid input for $(letter)ticks: $ticks")
|
||||
end
|
||||
@@ -1106,7 +1111,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
pyaxis."set_label_position"(axis[:guide_position])
|
||||
end
|
||||
py_set_scale(ax, sp, axis)
|
||||
axis[:ticks] != :native ? py_set_lims(ax, sp, axis) : nothing
|
||||
axis[:ticks] == :native ? nothing : py_set_lims(ax, sp, axis)
|
||||
if ispolar(sp) && letter == :y
|
||||
ax."set_rlabel_position"(90)
|
||||
end
|
||||
@@ -1115,10 +1120,22 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
if sp[:framestyle] == :origin && length(ticks) > 1
|
||||
ticks[2][ticks[1] .== 0] .= ""
|
||||
end
|
||||
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
|
||||
|
||||
# Set ticks
|
||||
fontProperties = PyPlot.PyCall.PyDict(Dict("family" => axis[:tickfontfamily],
|
||||
"size" => py_thickness_scale(plt, axis[:tickfontsize]),
|
||||
"useTex" => false,
|
||||
"rotation" => axis[:tickfontrotation]))
|
||||
getproperty(ax, Symbol("set_",letter,"ticklabels"))(getproperty(ax, Symbol("get_",letter,"ticks"))(), fontProperties)
|
||||
|
||||
# workaround to set mathtext.fontspec per Text element
|
||||
env = "\\mathregular" # matches the outer fonts https://matplotlib.org/tutorials/text/mathtext.html
|
||||
axis[:ticks] == :native ? nothing : py_set_ticks(ax, ticks, letter, env)
|
||||
|
||||
# Tick marks
|
||||
intensity = 0.5 # This value corresponds to scaling of other grid elements
|
||||
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in", width=py_thickness_scale(plt, intensity))
|
||||
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in", width=py_thickness_scale(plt, intensity),
|
||||
length= 5 * py_thickness_scale(plt, intensity))
|
||||
|
||||
getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide])
|
||||
if get(axis.plotattributes, :flip, false)
|
||||
@@ -1137,11 +1154,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
pyaxis."label"."set_rotation"(axis[:guidefontrotation])
|
||||
end
|
||||
|
||||
for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))()
|
||||
lab."set_fontsize"(py_thickness_scale(plt, axis[:tickfontsize]))
|
||||
lab."set_family"(axis[:tickfontfamily])
|
||||
lab."set_rotation"(axis[:rotation])
|
||||
end
|
||||
|
||||
if axis[:grid] && !(ticks in (:none, nothing, false))
|
||||
fgcolor = py_color(axis[:foreground_color_grid])
|
||||
pyaxis."grid"(true,
|
||||
|
||||
@@ -640,6 +640,9 @@ function process_annotation(sp::Subplot, positions::Union{AVec{Symbol},Symbol},
|
||||
anns
|
||||
end
|
||||
|
||||
function process_any_label(lab, font=Font())
|
||||
lab isa Tuple ? text(lab...) : text( lab, font )
|
||||
end
|
||||
# Give each annotation coordinates based on specified position
|
||||
function locate_annotation(sp::Subplot, pos::Symbol, lab::PlotText)
|
||||
position_multiplier = Dict{Symbol, Tuple{Float64,Float64}}(
|
||||
|
||||
+34
-3
@@ -885,6 +885,7 @@ const _examples = PlotExample[
|
||||
sv = SVector{10}(rand(10))
|
||||
ov = OffsetVector(rand(10), -2)
|
||||
plot([sv, ov], label = ["StaticArray" "OffsetArray"])
|
||||
plot!(3ov, ribbon=ov, label="OffsetArray ribbon")
|
||||
end
|
||||
end,
|
||||
],
|
||||
@@ -994,16 +995,45 @@ const _examples = PlotExample[
|
||||
scatter!(Point2.(eachcol(rand(d,1000))), alpha=0.25)
|
||||
end]
|
||||
),
|
||||
PlotExample(
|
||||
"Mesh3d",
|
||||
"""
|
||||
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically.
|
||||
You can also specify the connections using the connections keyword. This is only supported on the Plotly backend.
|
||||
The connections are specified using a tuple of vectors. Each vector contains the 0-based indices of one point of a triangle,
|
||||
such that elements at the same position of these vectors form a triangle.
|
||||
""",
|
||||
[
|
||||
:(
|
||||
begin
|
||||
# specify the vertices
|
||||
x=[0, 1, 2, 0]
|
||||
y=[0, 0, 1, 2]
|
||||
z=[0, 2, 0, 1]
|
||||
|
||||
# specify the triangles
|
||||
# every column is one triangle,
|
||||
# where the values denote the indices of the vertices of the triangle
|
||||
i=[0, 0, 0, 1]
|
||||
j=[1, 2, 3, 2]
|
||||
k=[2, 3, 1, 3]
|
||||
|
||||
# the four triangles gives above give a tetrahedron
|
||||
mesh3d(x,y,z;connections=(i,j,k))
|
||||
end
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
# Some constants for PlotDocs and PlotReferenceImages
|
||||
_animation_examples = [2, 31]
|
||||
_backend_skips = Dict(
|
||||
:gr => [25, 30],
|
||||
:pyplot => [2, 25, 30, 31],
|
||||
:gr => [25, 30, 47],
|
||||
:pyplot => [2, 25, 30, 31, 47],
|
||||
:plotlyjs => [2, 21, 24, 25, 30, 31],
|
||||
:plotly => [2, 21, 24, 25, 30, 31],
|
||||
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30, 31, 34, 37, 38, 39],
|
||||
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30, 31, 34, 37, 38, 39, 47],
|
||||
:pgfplotsx => [
|
||||
2, # animation
|
||||
6, # images
|
||||
@@ -1014,6 +1044,7 @@ _backend_skips = Dict(
|
||||
31, # animation
|
||||
32, # spy
|
||||
38, # histogram2d
|
||||
47, # mesh3d
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ function savefig(plt::Plot, fn::AbstractString)
|
||||
fn = abspath(expanduser(fn))
|
||||
|
||||
# get the extension
|
||||
fn, ext = splitext(fn)
|
||||
_, ext = splitext(fn)
|
||||
ext = chop(ext, head = 1, tail = 0)
|
||||
if isempty(ext)
|
||||
ext = defaultOutputFormat(plt)
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ RecipesPipeline.splittable_attribute(plt::Plot, key, val::SeriesAnnotations, len
|
||||
RecipesPipeline.splittable_attribute(plt, key, val.strs, len)
|
||||
|
||||
function RecipesPipeline.split_attribute(plt::Plot, key, val::SeriesAnnotations, indices)
|
||||
split_strs = _RecipesPipeline.split_attribute(key, val.strs, indices)
|
||||
split_strs = RecipesPipeline.split_attribute(key, val.strs, indices)
|
||||
return SeriesAnnotations(split_strs, val.font, val.baseshape, val.scalefactor)
|
||||
end
|
||||
|
||||
|
||||
+15
-1
@@ -913,6 +913,19 @@ end
|
||||
@deps pie shape
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mesh 3d replacement for non-plotly backends
|
||||
|
||||
@recipe function f(::Type{Val{:mesh3d}}, x, y, z)
|
||||
# As long as no i,j,k are supplied this should work with PyPlot and GR
|
||||
seriestype := :surface
|
||||
if plotattributes[:connections] != nothing
|
||||
throw(ArgumentError("Giving triangles using the connections argument is only supported on Plotly backend."))
|
||||
end
|
||||
()
|
||||
end
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# scatter 3d
|
||||
|
||||
@@ -928,7 +941,6 @@ end
|
||||
|
||||
# note: don't add dependencies because this really isn't a drop-in replacement
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# lens! - magnify a region of a plot
|
||||
lens!(args...;kwargs...) = plot!(args...; seriestype=:lens, kwargs...)
|
||||
@@ -1042,6 +1054,7 @@ function error_style!(plotattributes::AKW)
|
||||
end
|
||||
|
||||
plotattributes[:seriestype] = :path
|
||||
plotattributes[:markerstrokecolor] = msc
|
||||
plotattributes[:markercolor] = msc
|
||||
plotattributes[:linecolor] = msc
|
||||
plotattributes[:linewidth] = plotattributes[:markerstrokewidth]
|
||||
@@ -1533,3 +1546,4 @@ julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], f
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -318,6 +318,27 @@ julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
|
||||
"""
|
||||
@shorthands scatter3d
|
||||
|
||||
"""
|
||||
mesh3d(x,y,z)
|
||||
mesh3d(x,y,z; connections)
|
||||
|
||||
Plot a 3d mesh. On Plotly the triangles can be specified using the connections argument.
|
||||
|
||||
# Example
|
||||
```Julia
|
||||
x=[0, 1, 2, 0]
|
||||
y=[0, 0, 1, 2]
|
||||
z=[0, 2, 0, 1]
|
||||
|
||||
i=[0, 0, 0, 1]
|
||||
j=[1, 2, 3, 2]
|
||||
k=[2, 3, 1, 3]
|
||||
|
||||
plot(x,y,z,seriestype=:mesh3d;connections=(i,j,k))
|
||||
```
|
||||
"""
|
||||
@shorthands mesh3d
|
||||
|
||||
"""
|
||||
boxplot(x, y)
|
||||
boxplot!(x, y)
|
||||
|
||||
+24
-6
@@ -126,8 +126,8 @@ isnothing(x) = false
|
||||
_cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
|
||||
_cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
|
||||
|
||||
_cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
|
||||
_cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
|
||||
_cycle(v::AVec, idx::Int) = v[mod(idx, axes(v,1))]
|
||||
_cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[end, mod(idx, axes(v,2))] : v[:, mod(idx, axes(v,2))]
|
||||
_cycle(v, idx::Int) = v
|
||||
|
||||
_cycle(v::AVec, indices::AVec{Int}) = map(i -> _cycle(v,i), indices)
|
||||
@@ -362,10 +362,10 @@ end
|
||||
ok(tup::Tuple) = ok(tup...)
|
||||
|
||||
# compute one side of a fill range from a ribbon
|
||||
function make_fillrange_side(y, rib)
|
||||
frs = zeros(length(y))
|
||||
for (i, (yi, ri)) in enumerate(zip(y, Base.Iterators.cycle(rib)))
|
||||
frs[i] = yi + ri
|
||||
function make_fillrange_side(y::AVec, rib)
|
||||
frs = zeros(axes(y))
|
||||
for (i, yi) in pairs(y)
|
||||
frs[i] = yi + _cycle(rib,i)
|
||||
end
|
||||
frs
|
||||
end
|
||||
@@ -1004,6 +1004,24 @@ ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
|
||||
# ---------------------------------------------------------------
|
||||
# get fonts from objects:
|
||||
|
||||
plottitlefont(p::Plot) = font(
|
||||
p[:plot_titlefontfamily],
|
||||
p[:plot_titlefontsize],
|
||||
p[:plot_titlefontvalign],
|
||||
p[:plot_titlefonthalign],
|
||||
p[:plot_titlefontrotation],
|
||||
p[:plot_titlefontcolor],
|
||||
)
|
||||
|
||||
colorbartitlefont(sp::Subplot) = font(
|
||||
sp[:colorbar_titlefontfamily],
|
||||
sp[:colorbar_titlefontsize],
|
||||
sp[:colorbar_titlefontvalign],
|
||||
sp[:colorbar_titlefonthalign],
|
||||
sp[:colorbar_titlefontrotation],
|
||||
sp[:colorbar_titlefontcolor],
|
||||
)
|
||||
|
||||
titlefont(sp::Subplot) = font(
|
||||
sp[:titlefontfamily],
|
||||
sp[:titlefontsize],
|
||||
|
||||
+37
-7
@@ -302,6 +302,11 @@ end
|
||||
lines = readlines(io)
|
||||
@test count(s -> occursin("node", s), lines) == 9
|
||||
end
|
||||
# test .tikz extension
|
||||
file_path =joinpath(path,"annotations.tikz")
|
||||
@test_nowarn savefig(annotation_plot, file_path)
|
||||
@test_nowarn open(file_path) do io
|
||||
end
|
||||
end
|
||||
end # testset
|
||||
@testset "Ribbon" begin
|
||||
@@ -314,16 +319,12 @@ end
|
||||
Plots._update_plot_object(ribbon_plot)
|
||||
axis = Plots.pgfx_axes(ribbon_plot.o)[1]
|
||||
plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents)
|
||||
@test length(plots) == 4
|
||||
@test !haskey(plots[1].options.dict, "fill")
|
||||
@test !haskey(plots[2].options.dict, "fill")
|
||||
@test length(plots) == 3
|
||||
@test haskey(plots[1].options.dict, "fill")
|
||||
@test haskey(plots[2].options.dict, "fill")
|
||||
@test !haskey(plots[3].options.dict, "fill")
|
||||
@test haskey(plots[4].options.dict, "fill")
|
||||
@test ribbon_plot.o !== nothing
|
||||
@test ribbon_plot.o.the_plot !== nothing
|
||||
# mktempdir() do path
|
||||
# @test_nowarn savefig(ribbon_plot, path*"ribbon.svg")
|
||||
# end
|
||||
end # testset
|
||||
end # testset
|
||||
|
||||
@@ -345,4 +346,33 @@ end # testset
|
||||
axes = Plots.pgfx_axes(pl.o)
|
||||
@test !haskey(axes[1].options.dict, "axis line shift")
|
||||
@test haskey(axes[2].options.dict, "axis line shift")
|
||||
pl = plot(x->x, -1:1; add = raw"\node at (0,0.5) {\huge hi};", extra_kwargs = :subplot)
|
||||
@test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};")
|
||||
Plots._update_plot_object(pl)
|
||||
axes = Plots.pgfx_axes(pl.o)
|
||||
@test filter(x->x isa String, axes[1].contents)[1] == raw"\node at (0,0.5) {\huge hi};"
|
||||
plot!(pl)
|
||||
@test pl[1][:extra_kwargs] == Dict(:add => raw"\node at (0,0.5) {\huge hi};")
|
||||
Plots._update_plot_object(pl)
|
||||
axes = Plots.pgfx_axes(pl.o)
|
||||
@test filter(x->x isa String, axes[1].contents)[1] == raw"\node at (0,0.5) {\huge hi};"
|
||||
end # testset
|
||||
|
||||
@testset "Titlefonts" begin
|
||||
pl = plot(1:5, title = "Test me", titlefont = (2, :left))
|
||||
@test pl[1][:title] == "Test me"
|
||||
@test pl[1][:titlefontsize] == 2
|
||||
@test pl[1][:titlefonthalign] == :left
|
||||
Plots._update_plot_object(pl)
|
||||
ax_opt = Plots.pgfx_axes(pl.o)[1].options
|
||||
@test ax_opt["title"] == "Test me"
|
||||
@test(haskey(ax_opt.dict, "title style")) isa Test.Pass
|
||||
pl = plot(1:5, plot_title = "Test me", plot_titlefont = (2, :left))
|
||||
@test pl[:plot_title] == "Test me"
|
||||
@test pl[:plot_titlefontsize] == 2
|
||||
@test pl[:plot_titlefonthalign] == :left
|
||||
pl = heatmap(rand(3,3), colorbar_title = "Test me", colorbar_titlefont = (12, :right))
|
||||
@test pl[1][:colorbar_title] == "Test me"
|
||||
@test pl[1][:colorbar_titlefontsize] == 12
|
||||
@test pl[1][:colorbar_titlefonthalign] == :right
|
||||
end # testset
|
||||
|
||||
Reference in New Issue
Block a user