fixes/improvements to annotations; added series_annotations keyword
This commit is contained in:
parent
333c2765fe
commit
862ac3af8a
@ -159,6 +159,7 @@ _series_defaults[:contours] = false # add contours to 3d surface an
|
||||
_series_defaults[:match_dimensions] = false # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196
|
||||
# this ONLY effects whether or not the z-matrix is transposed for a heatmap display!
|
||||
_series_defaults[:subplot] = :auto # which subplot(s) does this series belong to?
|
||||
_series_defaults[:series_annotations] = [] # a list of annotations which apply to the coordinates of this series
|
||||
|
||||
|
||||
const _plot_defaults = KW()
|
||||
@ -199,7 +200,7 @@ _subplot_defaults[:legend] = :best
|
||||
_subplot_defaults[:colorbar] = :legend
|
||||
_subplot_defaults[:legendfont] = font(8)
|
||||
_subplot_defaults[:grid] = true
|
||||
_subplot_defaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation)
|
||||
_subplot_defaults[:annotations] = [] # annotation tuples... list of (x,y,annotation)
|
||||
# _subplot_defaults[:polar] = false
|
||||
_subplot_defaults[:projection] = :none # can also be :polar or :3d
|
||||
_subplot_defaults[:aspect_ratio] = :none # choose from :none or :equal
|
||||
@ -346,7 +347,7 @@ add_aliases(:fillrange, :fillrng, :frange, :fillto, :fill_between)
|
||||
add_aliases(:group, :g, :grouping)
|
||||
add_aliases(:bins, :bin, :nbin, :nbins, :nb)
|
||||
add_aliases(:ribbon, :rib)
|
||||
add_aliases(:annotation, :ann, :anns, :annotate, :annotations)
|
||||
add_aliases(:annotations, :ann, :anns, :annotate, :annotation)
|
||||
add_aliases(:xguide, :xlabel, :xlab, :xl)
|
||||
add_aliases(:xlims, :xlim, :xlimit, :xlimits)
|
||||
add_aliases(:xticks, :xtick)
|
||||
@ -385,6 +386,7 @@ add_aliases(:match_dimensions, :transpose, :transpose_z)
|
||||
add_aliases(:subplot, :sp, :subplt, :splt)
|
||||
add_aliases(:projection, :proj)
|
||||
add_aliases(:title_location, :title_loc, :titleloc)
|
||||
add_aliases(:series_annotations, :series_ann, :seriesann, :series_anns, :seriesanns, :series_annotation)
|
||||
|
||||
|
||||
# add all pluralized forms to the _keyAliases dict
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
supportedArgs(::BokehBackend) = [
|
||||
# :annotation,
|
||||
# :annotations,
|
||||
# :axis,
|
||||
# :background_color,
|
||||
:linecolor,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
supportedArgs(::GadflyBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
:background_color, :foreground_color, :color_palette,
|
||||
:group, :label, :seriestype,
|
||||
:seriescolor, :seriesalpha,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
# [WEBSITE]
|
||||
|
||||
supportedArgs(::GLVisualizeBackend) = [
|
||||
# :annotation,
|
||||
# :annotations,
|
||||
# :axis,
|
||||
# :background_color,
|
||||
# :color_palette,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
supportedArgs(::GRBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
:background_color, :foreground_color, :color_palette,
|
||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||
:foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
# https://plot.ly/javascript/getting-started
|
||||
|
||||
supportedArgs(::PlotlyBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
:background_color, :foreground_color, :color_palette,
|
||||
# :background_color_legend, :background_color_inside, :background_color_outside,
|
||||
# :foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
supportedArgs(::PyPlotBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
:background_color, :foreground_color, :color_palette,
|
||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||
:foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
|
||||
@ -1153,6 +1153,11 @@ function _update_plot(plt::Plot{PyPlotBackend}, d::KW)
|
||||
# ticksz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize
|
||||
# guidesz = get(d, :guidefont, attr[:guidefont]).pointsize
|
||||
|
||||
# add the annotations
|
||||
for ann in attr[:annotations]
|
||||
createPyPlotAnnotationObject(sp, ann...)
|
||||
end
|
||||
|
||||
# title
|
||||
if haskey(attr, :title)
|
||||
loc = lowercase(string(attr[:title_location]))
|
||||
@ -1252,28 +1257,28 @@ end
|
||||
|
||||
# TODO: these should apply to a Subplot, NOT a Plot
|
||||
|
||||
# function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::@compat(AbstractString))
|
||||
# ax = getLeftAxis(plt)
|
||||
# ax[:annotate](val, xy = (x,y))
|
||||
# end
|
||||
#
|
||||
#
|
||||
# function createPyPlotAnnotationObject(plt::Plot{PyPlotBackend}, x, y, val::PlotText)
|
||||
# ax = getLeftAxis(plt)
|
||||
# ax[:annotate](val.str,
|
||||
# xy = (x,y),
|
||||
# family = val.font.family,
|
||||
# color = getPyPlotColor(val.font.color),
|
||||
# horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign),
|
||||
# verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
|
||||
# rotation = val.font.rotation * 180 / π,
|
||||
# size = val.font.pointsize
|
||||
# )
|
||||
# end
|
||||
#
|
||||
# function _add_annotations{X,Y,V}(plt::Plot{PyPlotBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
|
||||
function createPyPlotAnnotationObject(sp::Subplot{PyPlotBackend}, x, y, val::@compat(AbstractString))
|
||||
ax = sp.o
|
||||
ax[:annotate](val, xy = (x,y))
|
||||
end
|
||||
|
||||
|
||||
function createPyPlotAnnotationObject(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
|
||||
ax = sp.o
|
||||
ax[:annotate](val.str,
|
||||
xy = (x,y),
|
||||
family = val.font.family,
|
||||
color = getPyPlotColor(val.font.color),
|
||||
horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign),
|
||||
verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
|
||||
rotation = val.font.rotation * 180 / π,
|
||||
size = val.font.pointsize
|
||||
)
|
||||
end
|
||||
|
||||
# function _add_annotations(sp::Subplot{PyPlotBackend}, anns::AVec)
|
||||
# for ann in anns
|
||||
# createPyPlotAnnotationObject(plt, ann...)
|
||||
# createPyPlotAnnotationObject(sp, ann...)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
supportedArgs(::QwtBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
:axis,
|
||||
:background_color,
|
||||
:linecolor,
|
||||
|
||||
@ -24,11 +24,11 @@ function _add_series(plt::Plot{[PkgName]Backend}, series::Series)
|
||||
# TODO: add one series to the underlying package
|
||||
end
|
||||
|
||||
function _add_annotations{X,Y,V}(plt::Plot{[PkgName]AbstractBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
|
||||
for ann in anns
|
||||
# TODO: add the annotation to the plot
|
||||
end
|
||||
end
|
||||
# function _add_annotations{X,Y,V}(plt::Plot{[PkgName]AbstractBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
|
||||
# for ann in anns
|
||||
# # TODO: add the annotation to the plot
|
||||
# end
|
||||
# end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
@ -61,13 +61,13 @@ end
|
||||
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
|
||||
# end
|
||||
|
||||
function _expand_limits(lims, plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# TODO: call expand limits for each plot data
|
||||
end
|
||||
|
||||
function _remove_axis(plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
|
||||
end
|
||||
# function _expand_limits(lims, plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# # TODO: call expand limits for each plot data
|
||||
# end
|
||||
#
|
||||
# function _remove_axis(plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# # TODO: if plot is inner subplot, might need to remove ticks or axis labels
|
||||
# end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
# https://github.com/Evizero/UnicodePlots.jl
|
||||
|
||||
supportedArgs(::UnicodePlotsBackend) = [
|
||||
# :annotation,
|
||||
# :annotations,
|
||||
# :args,
|
||||
# :axis,
|
||||
# :background_color,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation
|
||||
|
||||
supportedArgs(::WinstonBackend) = [
|
||||
:annotation,
|
||||
:annotations,
|
||||
# :args,
|
||||
# :axis,
|
||||
# :background_color,
|
||||
|
||||
@ -252,6 +252,7 @@ immutable PlotText
|
||||
end
|
||||
PlotText(str) = PlotText(string(str), font())
|
||||
|
||||
text(t::PlotText) = t
|
||||
function text(str, args...)
|
||||
PlotText(string(str), font(args...))
|
||||
end
|
||||
|
||||
104
src/plot.jl
104
src/plot.jl
@ -172,14 +172,14 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
args = tuple(extractGroupArgs(d[:group], args...), args...)
|
||||
end
|
||||
|
||||
# initialize the annotations list with what was passed in
|
||||
# TODO: there must be cleaner way to handle this!
|
||||
anns = annotations(get(d, :annotation, NTuple{3}[]))
|
||||
if typeof(anns) <: AVec{PlotText}
|
||||
anns = NTuple{3}[]
|
||||
else
|
||||
delete!(d, :annotation)
|
||||
end
|
||||
# # initialize the annotations list with what was passed in
|
||||
# # TODO: there must be cleaner way to handle this!
|
||||
# anns = annotations(get(d, :annotation, NTuple{3}[]))
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# anns = NTuple{3}[]
|
||||
# else
|
||||
# delete!(d, :annotation)
|
||||
# end
|
||||
|
||||
|
||||
# for plotting recipes, swap out the args and update the parameter dictionary
|
||||
@ -250,12 +250,12 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
|
||||
# !!! note: at this point, kw_list is fully decomposed into individual series... one KW per series !!!
|
||||
|
||||
# TODO: move annotations into subplot update
|
||||
# now include any annotations which were added during recipes
|
||||
for kw in kw_list
|
||||
append!(anns, annotations(pop!(kw, :annotation, [])))
|
||||
end
|
||||
# @show anns
|
||||
# # TODO: move annotations into subplot update
|
||||
# # now include any annotations which were added during recipes
|
||||
# for kw in kw_list
|
||||
# append!(anns, annotations(pop!(kw, :annotation, [])))
|
||||
# end
|
||||
# # @show anns
|
||||
|
||||
|
||||
# for kw in kw_list
|
||||
@ -296,6 +296,18 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
sp = kw[:subplot] = get_subplot(plt, sp)
|
||||
idx = get_subplot_index(plt, sp)
|
||||
|
||||
# strip out series annotations (those which are based on series x/y coords)
|
||||
# and add them to the subplot attr
|
||||
sp_anns = annotations(sp.attr[:annotations])
|
||||
anns = annotations(pop!(kw, :series_annotations, []))
|
||||
if length(anns) > 0
|
||||
x, y = kw[:x], kw[:y]
|
||||
nx, ny, na = map(length, (x,y,anns))
|
||||
n = max(nx, ny, na)
|
||||
anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(anns[mod1(i,na)])) for i=1:n]
|
||||
end
|
||||
sp.attr[:annotations] = vcat(sp_anns, anns)
|
||||
|
||||
# we update subplot args in case something like the color palatte is part of the recipe
|
||||
# DD(sp.attr[:xaxis].d, "before USA $i")
|
||||
# DD(kw, "kw")
|
||||
@ -319,8 +331,8 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
# DD(sp.attr[:xaxis].d, "after $i")
|
||||
end
|
||||
|
||||
# now that we're done adding all the series, add the annotations
|
||||
_add_annotations(plt, anns)
|
||||
# # now that we're done adding all the series, add the annotations
|
||||
# _add_annotations(plt, anns)
|
||||
|
||||
# TODO just need to pass plt... and we should do all non-series updates here
|
||||
_update_plot(plt, plt.plotargs)
|
||||
@ -484,38 +496,40 @@ end
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
annotations(::@compat(Void)) = []
|
||||
annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
|
||||
annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
|
||||
annotations(v::AVec{PlotText}) = v
|
||||
annotations(v::AVec) = map(PlotText, v)
|
||||
annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
|
||||
"(x, y, annotation)\n got: $(typeof(anns))")
|
||||
annotations(::Void) = []
|
||||
annotations(anns::AVec) = anns
|
||||
annotations(anns) = Any[anns]
|
||||
# annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
|
||||
# annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
|
||||
# annotations(v::AVec{PlotText}) = v
|
||||
# annotations(v::AVec) = map(PlotText, v)
|
||||
# annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
|
||||
# "(x, y, annotation)\n got: $(typeof(anns))")
|
||||
|
||||
function annotations(plt::Plot, anns)
|
||||
anns = annotations(anns)
|
||||
# if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
if typeof(anns) <: AVec{PlotText}
|
||||
x, y = plt[plt.n]
|
||||
anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
end
|
||||
anns
|
||||
end
|
||||
# function annotations(plt::Plot, anns)
|
||||
# anns = annotations(anns)
|
||||
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# x, y = plt[plt.n]
|
||||
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
# end
|
||||
# anns
|
||||
# end
|
||||
|
||||
|
||||
function _add_annotations(plt::Plot, d::KW)
|
||||
anns = annotations(get(d, :annotation, nothing))
|
||||
if !isempty(anns)
|
||||
|
||||
# if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
if typeof(anns) <: AVec{PlotText}
|
||||
x, y = plt[plt.n]
|
||||
anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
end
|
||||
|
||||
_add_annotations(plt, anns)
|
||||
end
|
||||
end
|
||||
# function _add_annotations(plt::Plot, d::KW)
|
||||
# anns = annotations(get(d, :annotation, nothing))
|
||||
# if !isempty(anns)
|
||||
#
|
||||
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# x, y = plt[plt.n]
|
||||
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
# end
|
||||
#
|
||||
# _add_annotations(plt, anns)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user