Merge pull request #2354 from BeastyBlacksmith/pgfplotsx
@JuliaRegistrator register()
This commit is contained in:
commit
dd70192de4
@ -1,7 +1,7 @@
|
|||||||
name = "Plots"
|
name = "Plots"
|
||||||
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
|
||||||
author = ["Tom Breloff (@tbreloff)"]
|
author = ["Tom Breloff (@tbreloff)"]
|
||||||
version = "0.28.4"
|
version = "0.28.5"
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||||
|
|||||||
@ -786,7 +786,6 @@ function processFillArg(plotattributes::KW, arg)
|
|||||||
plotattributes[:fillrange] = arg
|
plotattributes[:fillrange] = arg
|
||||||
|
|
||||||
elseif !handleColors!(plotattributes, arg, :fillcolor)
|
elseif !handleColors!(plotattributes, arg, :fillcolor)
|
||||||
|
|
||||||
plotattributes[:fillrange] = arg
|
plotattributes[:fillrange] = arg
|
||||||
end
|
end
|
||||||
# plotattributes[:fillrange] = fr
|
# plotattributes[:fillrange] = fr
|
||||||
|
|||||||
@ -34,6 +34,7 @@ function pgfx_axes(pgfx_plot::PGFPlotsXPlot)
|
|||||||
return gp isa PGFPlotsX.GroupPlot ? gp.contents : gp
|
return gp isa PGFPlotsX.GroupPlot ? gp.contents : gp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pgfx_preamble() = pgfx_preamble(current())
|
||||||
function pgfx_preamble(pgfx_plot::Plot{PGFPlotsXBackend})
|
function pgfx_preamble(pgfx_plot::Plot{PGFPlotsXBackend})
|
||||||
old_flag = pgfx_plot.attr[:tex_output_standalone]
|
old_flag = pgfx_plot.attr[:tex_output_standalone]
|
||||||
pgfx_plot.attr[:tex_output_standalone] = true
|
pgfx_plot.attr[:tex_output_standalone] = true
|
||||||
@ -82,17 +83,16 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
|||||||
if !any( sp -> ispolar(sp), plt.subplots )
|
if !any( sp -> ispolar(sp), plt.subplots )
|
||||||
pl_height, pl_width = plt.attr[:size]
|
pl_height, pl_width = plt.attr[:size]
|
||||||
push!( the_plot, PGFPlotsX.GroupPlot(
|
push!( the_plot, PGFPlotsX.GroupPlot(
|
||||||
PGFPlotsX.Options(
|
PGFPlotsX.Options(
|
||||||
"group style" => PGFPlotsX.Options(
|
"group style" => PGFPlotsX.Options(
|
||||||
"group size" => string(cols)*" by "*string(rows),
|
"group size" => string(cols)*" by "*string(rows),
|
||||||
"horizontal sep" => string(maximum(sp -> sp.minpad[1], plt.subplots)),
|
"horizontal sep" => string(maximum(sp -> sp.minpad[1], plt.subplots)),
|
||||||
"vertical sep" => string(maximum(sp -> sp.minpad[2], plt.subplots)),
|
"vertical sep" => string(maximum(sp -> sp.minpad[2], plt.subplots)),
|
||||||
),
|
),
|
||||||
"height" => pl_height > 0 ? string(pl_height * px) : "{}",
|
"height" => pl_height > 0 ? string(pl_height * px) : "{}",
|
||||||
"width" => pl_width > 0 ? string(pl_width * px) : "{}",
|
"width" => pl_width > 0 ? string(pl_width * px) : "{}",
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
))
|
||||||
end
|
end
|
||||||
for sp in plt.subplots
|
for sp in plt.subplots
|
||||||
bb = bbox(sp)
|
bb = bbox(sp)
|
||||||
@ -139,18 +139,18 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Search series for any gradient. In case one series uses a gradient set
|
# Search series for any gradient. In case one series uses a gradient set
|
||||||
# the colorbar and colomap.
|
# the colorbar and colomap.
|
||||||
# The reasoning behind doing this on the axis level is that pgfplots
|
# The reasoning behind doing this on the axis level is that pgfplots
|
||||||
# colorbar seems to only works on axis level and needs the proper colormap for
|
# colorbar seems to only works on axis level and needs the proper colormap for
|
||||||
# correctly displaying it.
|
# correctly displaying it.
|
||||||
# It's also possible to assign the colormap to the series itself but
|
# It's also possible to assign the colormap to the series itself but
|
||||||
# then the colormap needs to be added twice, once for the axis and once for the
|
# then the colormap needs to be added twice, once for the axis and once for the
|
||||||
# series.
|
# series.
|
||||||
# As it is likely that all series within the same axis use the same
|
# As it is likely that all series within the same axis use the same
|
||||||
# colormap this should not cause any problem.
|
# colormap this should not cause any problem.
|
||||||
for series in series_list(sp)
|
for series in series_list(sp)
|
||||||
for col in (:markercolor, :fillcolor, :linecolor)
|
for col in (:markercolor, :fillcolor, :linecolor)
|
||||||
if typeof(series.plotattributes[col]) == ColorGradient
|
if typeof(series.plotattributes[col]) == ColorGradient
|
||||||
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, """\\pgfplotsset{
|
PGFPlotsX.push_preamble!(pgfx_plot.the_plot, """\\pgfplotsset{
|
||||||
colormap={plots$(sp.attr[:subplot_index])}{$(pgfx_colormap(series.plotattributes[col]))},
|
colormap={plots$(sp.attr[:subplot_index])}{$(pgfx_colormap(series.plotattributes[col]))},
|
||||||
}""")
|
}""")
|
||||||
@ -158,141 +158,160 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend})
|
|||||||
"colorbar" => nothing,
|
"colorbar" => nothing,
|
||||||
"colormap name" => "plots$(sp.attr[:subplot_index])",
|
"colormap name" => "plots$(sp.attr[:subplot_index])",
|
||||||
)
|
)
|
||||||
# goto is needed to break out of col and series for
|
# goto is needed to break out of col and series for
|
||||||
@goto colorbar_end
|
@goto colorbar_end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@label colorbar_end
|
@label colorbar_end
|
||||||
|
|
||||||
push!(axis_opt, "colorbar style" => PGFPlotsX.Options(
|
push!(axis_opt, "colorbar style" => PGFPlotsX.Options(
|
||||||
"title" => sp[:colorbar_title],
|
"title" => sp[:colorbar_title],
|
||||||
"point meta max" => get_clims(sp)[2],
|
"point meta max" => get_clims(sp)[2],
|
||||||
"point meta min" => get_clims(sp)[1]
|
"point meta min" => get_clims(sp)[1]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if is3d(sp)
|
if is3d(sp)
|
||||||
azim, elev = sp[:camera]
|
azim, elev = sp[:camera]
|
||||||
push!( axis_opt, "view" => (azim, elev) )
|
push!( axis_opt, "view" => (azim, elev) )
|
||||||
end
|
end
|
||||||
axisf = if sp[:projection] == :polar
|
axisf = if sp[:projection] == :polar
|
||||||
# push!(axis_opt, "xmin" => 90)
|
# push!(axis_opt, "xmin" => 90)
|
||||||
# push!(axis_opt, "xmax" => 450)
|
# push!(axis_opt, "xmax" => 450)
|
||||||
PGFPlotsX.PolarAxis
|
PGFPlotsX.PolarAxis
|
||||||
else
|
else
|
||||||
PGFPlotsX.Axis
|
PGFPlotsX.Axis
|
||||||
end
|
end
|
||||||
axis = axisf(
|
axis = axisf(
|
||||||
axis_opt
|
axis_opt
|
||||||
)
|
)
|
||||||
for (series_index, series) in enumerate(series_list(sp))
|
for (series_index, series) in enumerate(series_list(sp))
|
||||||
opt = series.plotattributes
|
# give each series a uuid for fillbetween
|
||||||
st = series[:seriestype]
|
series_id = uuid4()
|
||||||
series_opt = PGFPlotsX.Options(
|
_pgfplotsx_series_ids[Symbol("$series_index")] = series_id
|
||||||
"color" => single_color(opt[:linecolor]),
|
opt = series.plotattributes
|
||||||
)
|
st = series[:seriestype]
|
||||||
if is3d(series) || st == :heatmap
|
sf = series[:fillrange]
|
||||||
series_func = PGFPlotsX.Plot3
|
series_opt = PGFPlotsX.Options(
|
||||||
else
|
"color" => single_color(opt[:linecolor]),
|
||||||
series_func = PGFPlotsX.Plot
|
"name path" => string(series_id)
|
||||||
end
|
)
|
||||||
if series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
|
if is3d(series) || st == :heatmap
|
||||||
push!(series_opt, "area legend" => nothing)
|
series_func = PGFPlotsX.Plot3
|
||||||
end
|
else
|
||||||
if st == :heatmap
|
series_func = PGFPlotsX.Plot
|
||||||
push!(axis.options,
|
end
|
||||||
"view" => "{0}{90}",
|
if sf !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
|
||||||
)
|
push!(series_opt, "area legend" => nothing)
|
||||||
end
|
end
|
||||||
# treat segments
|
if st == :heatmap
|
||||||
segments = if st in (:wireframe, :heatmap, :contour, :surface, :contour3d)
|
push!(axis.options,
|
||||||
iter_segments(surface_to_vecs(series[:x], series[:y], series[:z])...)
|
"view" => "{0}{90}",
|
||||||
else
|
)
|
||||||
iter_segments(series)
|
end
|
||||||
end
|
# treat segments
|
||||||
for (i, rng) in enumerate(segments)
|
segments = if st in (:wireframe, :heatmap, :contour, :surface, :contour3d)
|
||||||
segment_opt = PGFPlotsX.Options()
|
iter_segments(surface_to_vecs(series[:x], series[:y], series[:z])...)
|
||||||
segment_opt = merge( segment_opt, pgfx_linestyle(opt, i) )
|
else
|
||||||
if opt[:markershape] != :none
|
iter_segments(series)
|
||||||
marker = opt[:markershape]
|
end
|
||||||
if marker isa Shape
|
for (i, rng) in enumerate(segments)
|
||||||
x = marker.x
|
segment_opt = PGFPlotsX.Options()
|
||||||
y = marker.y
|
segment_opt = merge( segment_opt, pgfx_linestyle(opt, i) )
|
||||||
scale_factor = 0.025
|
if opt[:markershape] != :none
|
||||||
mark_size = opt[:markersize] * scale_factor
|
marker = opt[:markershape]
|
||||||
path = join(["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], " -- ")
|
if marker isa Shape
|
||||||
c = get_markercolor(series, i)
|
x = marker.x
|
||||||
a = get_markeralpha(series, i)
|
y = marker.y
|
||||||
PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
|
scale_factor = 0.025
|
||||||
"""
|
mark_size = opt[:markersize] * scale_factor
|
||||||
\\pgfdeclareplotmark{PlotsShape$(series_index)}{
|
path = join(["($(x[i] * mark_size), $(y[i] * mark_size))" for i in eachindex(x)], " -- ")
|
||||||
\\filldraw
|
c = get_markercolor(series, i)
|
||||||
$path;
|
a = get_markeralpha(series, i)
|
||||||
}
|
PGFPlotsX.push_preamble!(pgfx_plot.the_plot,
|
||||||
"""
|
"""
|
||||||
)
|
\\pgfdeclareplotmark{PlotsShape$(series_index)}{
|
||||||
end
|
\\filldraw
|
||||||
segment_opt = merge( segment_opt, pgfx_marker(opt, i) )
|
$path;
|
||||||
end
|
}
|
||||||
if st == :shape ||
|
"""
|
||||||
isfilledcontour(series)
|
)
|
||||||
segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
|
end
|
||||||
end
|
segment_opt = merge( segment_opt, pgfx_marker(opt, i) )
|
||||||
# add fillrange
|
end
|
||||||
if series[:fillrange] !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
|
if st == :shape ||
|
||||||
pgfx_fillrange_series!( axis, series, series_func, i, _cycle(series[:fillrange], rng), rng)
|
isfilledcontour(series)
|
||||||
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
|
segment_opt = merge( segment_opt, pgfx_fillstyle(opt, i) )
|
||||||
pgfx_filllegend!(series_opt, opt)
|
end
|
||||||
end
|
# add fillrange
|
||||||
end
|
if sf !== nothing && !isfilledcontour(series) && series[:ribbon] === nothing
|
||||||
# series
|
if sf isa Number || sf isa AVec
|
||||||
#
|
pgfx_fillrange_series!( axis, series, series_func, i, _cycle(sf, rng), rng)
|
||||||
coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng )
|
end
|
||||||
segment_plot = series_func(
|
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
|
||||||
merge(series_opt, segment_opt),
|
pgfx_filllegend!(series_opt, opt)
|
||||||
coordinates,
|
end
|
||||||
)
|
end
|
||||||
push!(axis, segment_plot)
|
# series
|
||||||
# add ribbons?
|
#
|
||||||
ribbon = series[:ribbon]
|
coordinates = pgfx_series_coordinates!( sp, series, segment_opt, opt, rng )
|
||||||
if ribbon !== nothing
|
segment_plot = series_func(
|
||||||
pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
|
merge(series_opt, segment_opt),
|
||||||
end
|
coordinates,
|
||||||
# add to legend?
|
)
|
||||||
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
|
push!(axis, segment_plot)
|
||||||
leg_opt = PGFPlotsX.Options()
|
# fill between functions
|
||||||
if ribbon !== nothing
|
if sf isa Tuple && series[:ribbon] === nothing
|
||||||
pgfx_filllegend!(axis.contents[end-3].options, opt)
|
sf1, sf2 = sf
|
||||||
end
|
@assert sf1 == series_index "First index of the tuple has to match the current series index."
|
||||||
legend = PGFPlotsX.LegendEntry(leg_opt, opt[:label], false)
|
push!(axis, series_func(
|
||||||
push!( axis, legend )
|
merge(pgfx_fillstyle(opt, series_index), PGFPlotsX.Options("forget plot" => nothing)),
|
||||||
end
|
"fill between [of=$series_id and $(_pgfplotsx_series_ids[Symbol(string(sf2))])]"
|
||||||
# add series annotations
|
))
|
||||||
anns = series[:series_annotations]
|
end
|
||||||
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
|
# add ribbons?
|
||||||
pgfx_add_annotation!(axis, xi, yi, PlotText(str, fnt), pgfx_thickness_scaling(series))
|
ribbon = series[:ribbon]
|
||||||
end
|
if ribbon !== nothing
|
||||||
end
|
pgfx_add_ribbons!( axis, series, segment_plot, series_func, series_index )
|
||||||
# add subplot annotations
|
end
|
||||||
anns = sp.attr[:annotations]
|
# add to legend?
|
||||||
for (xi,yi,txt) in anns
|
if i == 1 && opt[:label] != "" && sp[:legend] != :none && should_add_to_legend(series)
|
||||||
pgfx_add_annotation!(axis, xi, yi, txt, pgfx_thickness_scaling(sp))
|
leg_opt = PGFPlotsX.Options()
|
||||||
end
|
if ribbon !== nothing
|
||||||
end
|
pgfx_filllegend!(axis.contents[end-3].options, opt)
|
||||||
if ispolar(sp)
|
end
|
||||||
axes = the_plot
|
legend = PGFPlotsX.LegendEntry(leg_opt, opt[:label], false)
|
||||||
else
|
push!( axis, legend )
|
||||||
axes = the_plot.elements[1]
|
end
|
||||||
end
|
# add series annotations
|
||||||
push!( axes, axis )
|
anns = series[:series_annotations]
|
||||||
if length(plt.o.the_plot.elements) > 0
|
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
|
||||||
plt.o.the_plot.elements[1] = the_plot
|
pgfx_add_annotation!(axis, xi, yi, PlotText(str, fnt), pgfx_thickness_scaling(series))
|
||||||
else
|
end
|
||||||
push!(plt.o, the_plot)
|
end
|
||||||
end
|
# add subplot annotations
|
||||||
end
|
for ann in sp[:annotations]
|
||||||
|
pgfx_add_annotation!(axis, locate_annotation(sp, ann...)..., pgfx_thickness_scaling(sp))
|
||||||
|
end
|
||||||
|
# anns = sp.attr[:annotations]
|
||||||
|
# for (xi,yi,txt) in anns
|
||||||
|
# pgfx_add_annotation!(axis, xi, yi, txt, pgfx_thickness_scaling(sp))
|
||||||
|
# end
|
||||||
|
end # for series
|
||||||
|
if ispolar(sp)
|
||||||
|
axes = the_plot
|
||||||
|
else
|
||||||
|
axes = the_plot.elements[1]
|
||||||
|
end
|
||||||
|
push!( axes, axis )
|
||||||
|
if length(plt.o.the_plot.elements) > 0
|
||||||
|
plt.o.the_plot.elements[1] = the_plot
|
||||||
|
else
|
||||||
|
push!(plt.o, the_plot)
|
||||||
|
end
|
||||||
|
end # for subplots
|
||||||
pgfx_plot.is_created = true
|
pgfx_plot.is_created = true
|
||||||
end
|
end # if
|
||||||
return pgfx_plot
|
return pgfx_plot
|
||||||
end
|
end
|
||||||
## seriestype specifics
|
## seriestype specifics
|
||||||
@ -438,6 +457,8 @@ const _pgfplotsx_linestyles = KW(
|
|||||||
:dashdotdot => "dashdotdotted",
|
:dashdotdot => "dashdotdotted",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const _pgfplotsx_series_ids = KW()
|
||||||
|
|
||||||
const _pgfplotsx_markers = KW(
|
const _pgfplotsx_markers = KW(
|
||||||
:none => "none",
|
:none => "none",
|
||||||
:cross => "+",
|
:cross => "+",
|
||||||
@ -524,7 +545,7 @@ function pgfx_framestyle(style::Symbol)
|
|||||||
return style
|
return style
|
||||||
else
|
else
|
||||||
default_style = get(_pgfx_framestyle_defaults, style, :axes)
|
default_style = get(_pgfx_framestyle_defaults, style, :axes)
|
||||||
@warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.")
|
@warn("Framestyle :$style is not (yet) supported by the PGFPlotsX backend. :$default_style was cosen instead.")
|
||||||
default_style
|
default_style
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -13,6 +13,7 @@ const DataPoint = Union{MaybeNumber, MaybeString}
|
|||||||
|
|
||||||
prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting")
|
prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting")
|
||||||
prepareSeriesData(::Nothing) = nothing
|
prepareSeriesData(::Nothing) = nothing
|
||||||
|
prepareSeriesData(t::Tuple{T, T}) where {T<:Number} = t
|
||||||
prepareSeriesData(f::Function) = f
|
prepareSeriesData(f::Function) = f
|
||||||
prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!(
|
prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!(
|
||||||
x -> ismissing(x) || isinf(x) ? NaN : x,
|
x -> ismissing(x) || isinf(x) ? NaN : x,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user