fixes/improvements to annotations; added series_annotations keyword

This commit is contained in:
Thomas Breloff 2016-05-20 11:38:07 -04:00
parent 333c2765fe
commit 862ac3af8a
13 changed files with 111 additions and 89 deletions

View File

@ -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

View File

@ -3,7 +3,7 @@
supportedArgs(::BokehBackend) = [
# :annotation,
# :annotations,
# :axis,
# :background_color,
:linecolor,

View File

@ -3,7 +3,7 @@
supportedArgs(::GadflyBackend) = [
:annotation,
:annotations,
:background_color, :foreground_color, :color_palette,
:group, :label, :seriestype,
:seriescolor, :seriesalpha,

View File

@ -3,7 +3,7 @@
# [WEBSITE]
supportedArgs(::GLVisualizeBackend) = [
# :annotation,
# :annotations,
# :axis,
# :background_color,
# :color_palette,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -3,7 +3,7 @@
supportedArgs(::QwtBackend) = [
:annotation,
:annotations,
:axis,
:background_color,
:linecolor,

View File

@ -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
# ----------------------------------------------------------------

View File

@ -2,7 +2,7 @@
# https://github.com/Evizero/UnicodePlots.jl
supportedArgs(::UnicodePlotsBackend) = [
# :annotation,
# :annotations,
# :args,
# :axis,
# :background_color,

View File

@ -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,

View File

@ -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

View File

@ -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
# --------------------------------------------------------------------