Compare commits

..

13 Commits

Author SHA1 Message Date
Thomas Breloff f3544dc826 plotlyjs png fix; NEWS update for 0.7.2 2016-06-16 20:58:44 -04:00
Thomas Breloff b0bc68ae8a orientation aliases dir/direction; removed native support for sticks/hline/vline in pyplot; commented out arcdiagram 2016-06-16 17:31:10 -04:00
Thomas Breloff c38e947dc6 animation default file tempname; raised group warning to 100; check for empty vec in axis; use command_idx for slicing; move deletion of smooth outside loop 2016-06-16 10:03:01 -04:00
Thomas Breloff ec826fc8ce moved series_annotations into series recipe processing; change pyplot clf to fig clear 2016-06-16 00:48:35 -04:00
Thomas Breloff e5c4f782a5 anynan isfinite; error on reusing layout 2016-06-15 15:36:36 -04:00
Thomas Breloff a5ddebf44d curves fix 2016-06-15 13:02:31 -04:00
Thomas Breloff 38804898c5 iter_segments and curve series type 2016-06-15 12:52:36 -04:00
Thomas Breloff 2bd67f3519 pyplot 3d line segments 2016-06-15 02:15:51 -04:00
Thomas Breloff c8ed611c9c unicodeplots cleanup: ijulia output fixes, ascii canvas 2016-06-15 01:45:13 -04:00
Thomas Breloff 3d7d8caa82 moved pyplot methods _series_added and _initialize_subplot into the display pipeline 2016-06-14 18:02:44 -04:00
Thomas Breloff f64108523c line_z arg and pyplot implementation 2016-06-14 15:39:21 -04:00
Tom Breloff a7493504ed Merge pull request #334 from jheinen/dev
conserve user defined GR workstation type
2016-06-14 13:31:40 -04:00
Josef Heinen bc5293b5a4 conserve user defined GR workstation type 2016-06-14 18:03:03 +02:00
16 changed files with 445 additions and 335 deletions
+13
View File
@@ -9,6 +9,19 @@
## 0.7 (current master/dev)
#### 0.7.2
- line_z arg for multicolored line segments
- pyplot
- line_z (2d and 3d)
- pushed all fig updates into display pipeline
- remove native sticks/hline/vline in favor of recipes
- unicodeplots cleanup, ijulia fixes, ascii canvas
- `curves` series type
- `iter_segments` iterator
- moved arcdiagram out and into PlotRecipes (thanks @diegozea)
- several other fixes/checks
#### 0.7.1
- inset (floating) subplots
+2
View File
@@ -109,6 +109,7 @@ export
chorddiagram,
test_examples,
iter_segments,
translate,
translate!,
@@ -183,6 +184,7 @@ end
@shorthands boxplot
@shorthands violin
@shorthands quiver
@shorthands curves
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
+1 -1
View File
@@ -24,7 +24,7 @@ immutable AnimatedGif
filename::Compat.ASCIIString
end
function gif(anim::Animation, fn = "tmp.gif"; fps::Integer = 20)
function gif(anim::Animation, fn = tempname()*".gif"; fps::Integer = 20)
fn = abspath(fn)
try
+2 -1
View File
@@ -27,7 +27,8 @@ const _arg_desc = KW(
:x => "Various. Input data. First Dimension",
:y => "Various. Input data. Second Dimension",
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
:marker_z => "AbstractVector. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.",
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
+19 -2
View File
@@ -11,6 +11,16 @@ function add_aliases(sym::Symbol, aliases::Symbol...)
end
end
function add_non_underscore_aliases!(aliases::KW)
for (k,v) in aliases
s = string(k)
if '_' in s
aliases[Symbol(replace(s, "_", ""))] = v
end
end
end
# ------------------------------------------------------------
const _allAxes = [:auto, :left, :right]
@@ -61,8 +71,12 @@ const _allTypes = vcat([
:imagesc => :image,
:hist => :histogram,
:hist2d => :histogram2d,
:bezier => :curves,
:bezier_curves => :curves,
)
add_non_underscore_aliases!(_typeAliases)
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :density)
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
like_surface(seriestype::Symbol) = seriestype in (:contour, :contour3d, :heatmap, :surface, :wireframe, :image)
@@ -163,6 +177,7 @@ const _series_defaults = KW(
:y => nothing,
:z => nothing, # depth for contour, surface, etc
:marker_z => nothing, # value for color scale
:line_z => nothing,
:levels => 15,
:orientation => :vertical,
:bar_position => :overlay, # for bar plots and histograms: could also be stack (stack up) or dodge (side by side)
@@ -375,7 +390,8 @@ add_aliases(:linestyle, :style, :s, :ls)
add_aliases(:marker, :m, :mark)
add_aliases(:markershape, :shape)
add_aliases(:markersize, :ms, :msize)
add_aliases(:marker_z, :markerz, :zcolor)
add_aliases(:marker_z, :markerz, :zcolor, :mz)
add_aliases(:line_z, :linez, :zline, :lz)
add_aliases(:fill, :f, :area)
add_aliases(:fillrange, :fillrng, :frange, :fillto, :fill_between)
add_aliases(:group, :g, :grouping)
@@ -415,6 +431,7 @@ add_aliases(:projection, :proj)
add_aliases(:title_location, :title_loc, :titleloc, :title_position, :title_pos, :titlepos, :titleposition, :title_align, :title_alignment)
add_aliases(:series_annotations, :series_ann, :seriesann, :series_anns, :seriesanns, :series_annotation)
add_aliases(:html_output_format, :format, :fmt, :html_format)
add_aliases(:orientation, :direction, :dir)
# add all pluralized forms to the _keyAliases dict
@@ -696,7 +713,7 @@ end
function extractGroupArgs(v::AVec, args...)
groupLabels = sort(collect(unique(v)))
n = length(groupLabels)
if n > 20
if n > 100
warn("You created n=$n groups... Is that intended?")
end
groupIds = Vector{Int}[filter(i -> v[i] == glab, 1:length(v)) for glab in groupLabels]
+2 -1
View File
@@ -895,11 +895,12 @@ const _gr_mimeformats = Dict(
for (mime, fmt) in _gr_mimeformats
@eval function _writemime(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GRBackend})
GR.emergencyclosegks()
wstype = haskey(ENV, "GKS_WSTYPE") ? ENV["GKS_WSTYPE"] : "0"
ENV["GKS_WSTYPE"] = $fmt
gr_display(plt)
GR.emergencyclosegks()
write(io, readall("gks." * $fmt))
ENV["GKS_WSTYPE"] = ""
ENV["GKS_WSTYPE"] = wstype
end
end
+1 -1
View File
@@ -65,7 +65,7 @@ function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend})
end
function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend})
tmpfn = tempname() * "png"
tmpfn = tempname() * ".png"
PlotlyJS.savefig(plt.o, tmpfn)
write(io, read(open(tmpfn)))
end
+131 -78
View File
@@ -18,7 +18,9 @@ supported_args(::PyPlotBackend) = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:marker_z,
:line_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
:overwrite_figure,
@@ -32,8 +34,8 @@ supported_args(::PyPlotBackend) = merge_with_base_supported([
supported_types(::PyPlotBackend) = [
:path, :steppre, :steppost, :shape,
:scatter, :histogram2d, :hexbin, :histogram,
:bar, :sticks,
:hline, :vline, :heatmap, :pie, :image,
:bar,
:heatmap, :pie, :image,
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
]
supported_styles(::PyPlotBackend) = [:auto, :solid, :dash, :dot, :dashdot]
@@ -61,6 +63,8 @@ function _initialize_backend(::PyPlotBackend)
const pycmap = PyPlot.pywrap(PyPlot.pyimport("matplotlib.cm"))
const pynp = PyPlot.pywrap(PyPlot.pyimport("numpy"))
const pytransforms = PyPlot.pywrap(PyPlot.pyimport("matplotlib.transforms"))
const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections"))
const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d"))
end
# we don't want every command to update the figure
@@ -339,12 +343,14 @@ function _create_backend_figure(plt::Plot{PyPlotBackend})
end
# clear the figure
PyPlot.clf()
# PyPlot.clf()
fig
end
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
# function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
function py_init_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
fig = plt.o
proj = sp[:projection]
proj = (proj in (nothing,:none) ? nothing : string(proj))
@@ -364,7 +370,9 @@ end
# function _series_added(pkg::PyPlotBackend, plt::Plot, d::KW)
# TODO: change this to accept Subplot??
function _series_added(plt::Plot{PyPlotBackend}, series::Series)
# function _series_added(plt::Plot{PyPlotBackend}, series::Series)
function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
d = series.d
st = d[:seriestype]
sp = d[:subplot]
@@ -406,17 +414,49 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
# line plot
if st in (:path, :path3d, :steppre, :steppost)
if d[:linewidth] > 0
handle = ax[:plot](xyargs...;
label = d[:label],
zorder = plt.n,
color = py_linecolor(d),
linewidth = d[:linewidth],
linestyle = py_linestyle(st, d[:linestyle]),
solid_capstyle = "round",
# dash_capstyle = "round",
drawstyle = py_stepstyle(st)
)[1]
push!(handles, handle)
if d[:line_z] == nothing
handle = ax[:plot](xyargs...;
label = d[:label],
zorder = plt.n,
color = py_linecolor(d),
linewidth = d[:linewidth],
linestyle = py_linestyle(st, d[:linestyle]),
solid_capstyle = "round",
drawstyle = py_stepstyle(st)
)[1]
push!(handles, handle)
else
# multicolored line segments
n = length(x) - 1
segments = Array(Any,n)
kw = KW(
:label => d[:label],
:zorder => plt.n,
:cmap => py_linecolormap(d),
:linewidth => d[:linewidth],
:linestyle => py_linestyle(st, d[:linestyle])
)
handle = if is3d(st)
for i=1:n
segments[i] = [(cycle(x,i), cycle(y,i), cycle(z,i)), (cycle(x,i+1), cycle(y,i+1), cycle(z,i+1))]
end
lc = pyart3d.Line3DCollection(segments; kw...)
lc[:set_array](d[:line_z])
ax[:add_collection3d](lc, zs=z) #, zdir='y')
lc
else
for i=1:n
segments[i] = [(cycle(x,i), cycle(y,i)), (cycle(x,i+1), cycle(y,i+1))]
end
lc = pycollections.LineCollection(segments; kw...)
lc[:set_array](d[:line_z])
ax[:add_collection](lc)
lc
end
push!(handles, handle)
needs_colorbar = true
end
a = d[:arrow]
if a != nothing && !is3d(st) # TODO: handle 3d later
@@ -468,24 +508,24 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
push!(handles, handle)
end
if st == :sticks
extrakw[isvertical(d) ? :width : :height] = 0.0
handle = ax[isvertical(d) ? :bar : :barh](x, y;
label = d[:label],
zorder = plt.n,
color = py_linecolor(d),
edgecolor = py_linecolor(d),
linewidth = d[:linewidth],
align = "center",
extrakw...
)[1]
push!(handles, handle)
end
# if st == :sticks
# extrakw[isvertical(d) ? :width : :height] = 0.0
# handle = ax[isvertical(d) ? :bar : :barh](x, y;
# label = d[:label],
# zorder = plt.n,
# color = py_linecolor(d),
# edgecolor = py_linecolor(d),
# linewidth = d[:linewidth],
# align = "center",
# extrakw...
# )[1]
# push!(handles, handle)
# end
# add markers?
if d[:markershape] != :none && st in (:path, :scatter, :path3d,
:scatter3d, :steppre, :steppost,
:bar, :sticks)
:bar)
extrakw = KW()
if d[:marker_z] == nothing
extrakw[:c] = py_color_fix(py_markercolor(d), x)
@@ -493,13 +533,13 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:c] = convert(Vector{Float64}, d[:marker_z])
extrakw[:cmap] = py_markercolormap(d)
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
needs_colorbar = true
end
xyargs = if st in (:bar, :sticks) && !isvertical(d)
xyargs = if st == :bar && !isvertical(d)
(y, x)
else
xyargs
@@ -542,7 +582,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
if st == :histogram2d
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -567,7 +607,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
if st == :hexbin
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -584,17 +624,17 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
needs_colorbar = true
end
if st in (:hline,:vline)
for yi in d[:y]
func = ax[st == :hline ? :axhline : :axvline]
handle = func(yi;
linewidth=d[:linewidth],
color=py_linecolor(d),
linestyle=py_linestyle(st, d[:linestyle])
)
push!(handles, handle)
end
end
# if st in (:hline,:vline)
# for yi in d[:y]
# func = ax[st == :hline ? :axhline : :axvline]
# handle = func(yi;
# linewidth=d[:linewidth],
# color=py_linecolor(d),
# linestyle=py_linestyle(st, d[:linestyle])
# )
# push!(handles, handle)
# end
# end
if st in (:contour, :contour3d)
# z = z.surf'
@@ -602,7 +642,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
needs_colorbar = true
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -648,7 +688,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:facecolors] = py_shading(d[:fillcolor], d[:marker_z], d[:fillalpha])
extrakw[:shade] = false
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -690,7 +730,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
elseif typeof(z) <: AbstractVector
# tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots)
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -744,7 +784,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
end
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@@ -852,28 +892,28 @@ end
# --------------------------------------------------------------------------
function update_limits!(sp::Subplot{PyPlotBackend}, series::Series, letters)
for letter in letters
py_set_lims(sp.o, sp[Symbol(letter, :axis)])
end
end
# function update_limits!(sp::Subplot{PyPlotBackend}, series::Series, letters)
# for letter in letters
# py_set_lims(sp.o, sp[Symbol(letter, :axis)])
# end
# end
function _series_updated(plt::Plot{PyPlotBackend}, series::Series)
d = series.d
for handle in d[:serieshandle]
if is3d(series)
handle[:set_data](d[:x], d[:y])
handle[:set_3d_properties](d[:z])
else
try
handle[:set_data](d[:x], d[:y])
catch
handle[:set_offsets](hcat(d[:x], d[:y]))
end
end
end
update_limits!(d[:subplot], series, is3d(series) ? (:x,:y,:z) : (:x,:y))
end
# function _series_updated(plt::Plot{PyPlotBackend}, series::Series)
# d = series.d
# for handle in get(d, :serieshandle, [])
# if is3d(series)
# handle[:set_data](d[:x], d[:y])
# handle[:set_3d_properties](d[:z])
# else
# try
# handle[:set_data](d[:x], d[:y])
# catch
# handle[:set_offsets](hcat(d[:x], d[:y]))
# end
# end
# end
# update_limits!(d[:subplot], series, is3d(series) ? (:x,:y,:z) : (:x,:y))
# end
# --------------------------------------------------------------------------
@@ -912,7 +952,10 @@ function py_compute_axis_minval(axis::Axis)
minval = 1.0
sp = axis.sp
for series in series_list(axis.sp)
minval = min(minval, minimum(abs(series.d[axis[:letter]])))
v = series.d[axis[:letter]]
if !isempty(v)
minval = min(minval, minimum(abs(v)))
end
end
# now if the axis limits go to a smaller abs value, use that instead
@@ -963,9 +1006,10 @@ end
function _before_layout_calcs(plt::Plot{PyPlotBackend})
# update the specs
# update the fig
w, h = plt[:size]
fig = plt.o
fig[:clear]()
fig[:set_size_inches](px2inch(w), px2inch(h), forward = true)
fig[:set_facecolor](py_color(plt[:background_color_outside]))
fig[:set_dpi](DPI)
@@ -973,9 +1017,18 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# resize the window
PyPlot.plt[:get_current_fig_manager]()[:resize](w, h)
# initialize subplots
for sp in plt.subplots
py_init_subplot(plt, sp)
end
# add the series
for series in plt.series_list
py_add_series(plt, series)
end
# update subplots
for sp in plt.subplots
# ax = getAxis(sp)
ax = sp.o
if ax == nothing
continue
@@ -989,16 +1042,16 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
# title
if sp[:title] != ""
loc = lowercase(string(sp[:title_location]))
field = if loc == "left"
func = if loc == "left"
:_left_title
elseif loc == "right"
:_right_title
else
:title
end
ax[field][:set_text](sp[:title])
ax[field][:set_fontsize](sp[:titlefont].pointsize)
ax[field][:set_color](py_color(sp[:foreground_color_title]))
ax[func][:set_text](sp[:title])
ax[func][:set_fontsize](sp[:titlefont].pointsize)
ax[func][:set_color](py_color(sp[:foreground_color_title]))
# ax[:set_title](sp[:title], loc = loc)
end
+53 -182
View File
@@ -4,12 +4,12 @@
supported_args(::UnicodePlotsBackend) = merge_with_base_supported([
:label,
:legend,
:seriescolor, :seriesalpha,
:seriescolor,
:seriesalpha,
:linestyle,
:markershape,
:bins,
:title,
:window_title,
:guide, :lims,
])
supported_types(::UnicodePlotsBackend) = [
@@ -28,19 +28,19 @@ warnOnUnsupported_args(pkg::UnicodePlotsBackend, d::KW) = nothing
# --------------------------------------------------------------------------------------
function _initialize_backend(::UnicodePlotsBackend; kw...)
@eval begin
import UnicodePlots
export UnicodePlots
end
@eval begin
import UnicodePlots
export UnicodePlots
end
end
# -------------------------------
# convert_size_from_pixels(sz) =
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
function rebuildUnicodePlot!(plt::Plot)
plt.o = []
for sp in plt.subplots
xaxis = sp[:xaxis]
yaxis = sp[:yaxis]
@@ -58,12 +58,14 @@ function rebuildUnicodePlot!(plt::Plot)
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
width, height = plt[:size]
o = UnicodePlots.Plot(x, y;
canvas_type = isijulia() ? UnicodePlots.AsciiCanvas : UnicodePlots.BrailleCanvas
o = UnicodePlots.Plot(x, y, canvas_type;
width = width,
height = height,
title = sp[:title],
xlim = xlim,
ylim = ylim
ylim = ylim,
border = isijulia() ? :ascii : :solid
)
# set the axis labels
@@ -80,213 +82,82 @@ function rebuildUnicodePlot!(plt::Plot)
end
end
# # do all the magic here... build it all at once, since we need to know about all the series at the very beginning
# function rebuildUnicodePlot!(plt::Plot)
#
# # figure out the plotting area xlim = [xmin, xmax] and ylim = [ymin, ymax]
# sargs = plt.seriesargs
# iargs = plt.attr
#
# # get the x/y limits
# if get(iargs, :xlims, :auto) == :auto
# xlim = [Inf, -Inf]
# for d in sargs
# _expand_limits(xlim, d[:x])
# end
# else
# xmin, xmax = iargs[:xlims]
# xlim = [xmin, xmax]
# end
#
# if get(iargs, :ylims, :auto) == :auto
# ylim = [Inf, -Inf]
# for d in sargs
# _expand_limits(ylim, d[:y])
# end
# else
# ymin, ymax = iargs[:ylims]
# ylim = [ymin, ymax]
# end
#
# # we set x/y to have a single point, since we need to create the plot with some data.
# # since this point is at the bottom left corner of the plot, it shouldn't actually be shown
# x = Float64[xlim[1]]
# y = Float64[ylim[1]]
#
# # create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
# width, height = iargs[:size]
# o = UnicodePlots.Plot(x, y; width = width,
# height = height,
# title = iargs[:title],
# # labels = iargs[:legend],
# xlim = xlim,
# ylim = ylim)
#
# # set the axis labels
# UnicodePlots.xlabel!(o, iargs[:xguide])
# UnicodePlots.ylabel!(o, iargs[:yguide])
#
# # now use the ! functions to add to the plot
# for d in sargs
# addUnicodeSeries!(o, d, iargs[:legend] != :none, xlim, ylim)
# end
#
# # save the object
# plt.o = o
# end
# add a single series
function addUnicodeSeries!(o, d::KW, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
st = d[:seriestype]
# handle hline/vline separately
if st in (:hline,:vline)
for yi in d[:y]
if st == :hline
UnicodePlots.lineplot!(o, xlim, [yi,yi])
else
UnicodePlots.lineplot!(o, [yi,yi], ylim)
end
end
return
# elseif st == :bar
# UnicodePlots.barplot!(o, d[:x], d[:y])
# return
# elseif st == :histogram
# UnicodePlots.histogram!(o, d[:y], bins = d[:bins])
# return
elseif st == :histogram2d
if st == :histogram2d
UnicodePlots.densityplot!(o, d[:x], d[:y])
return
end
stepstyle = :post
if st == :path
func = UnicodePlots.lineplot!
elseif st == :scatter || d[:markershape] != :none
func = UnicodePlots.scatterplot!
elseif st == :steppost
func = UnicodePlots.stairs!
elseif st == :steppre
func = UnicodePlots.stairs!
stepstyle = :pre
else
error("Linestyle $st not supported by UnicodePlots")
end
if st == :path
func = UnicodePlots.lineplot!
elseif st == :scatter || d[:markershape] != :none
func = UnicodePlots.scatterplot!
else
error("Linestyle $st not supported by UnicodePlots")
end
# get the series data and label
x, y = [collect(float(d[s])) for s in (:x, :y)]
label = addlegend ? d[:label] : ""
# get the series data and label
x, y = [collect(float(d[s])) for s in (:x, :y)]
label = addlegend ? d[:label] : ""
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = d[:linecolor] in UnicodePlots.color_cycle ? d[:linecolor] : :auto
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = d[:linecolor] in UnicodePlots.color_cycle ? d[:linecolor] : :auto
# add the series
func(o, x, y; color = color, name = label, style = stepstyle)
# add the series
func(o, x, y; color = color, name = label)
end
# function handlePlotColors(::UnicodePlotsBackend, d::KW)
# # TODO: something special for unicodeplots, since it doesn't take kindly to people messing with its color palette
# d[:color_palette] = [RGB(0,0,0)]
# end
# -------------------------------
# function _create_plot(pkg::UnicodePlotsBackend, d::KW)
# plt = Plot(nothing, pkg, 0, d, KW[])
function _create_backend_figure(plt::Plot{UnicodePlotsBackend})
# do we want to give a new default size?
# if !haskey(plt.attr, :size) || plt.attr[:size] == default(:size)
# plt.attr[:size] = (60,20)
# end
w, h = plt[:size]
plt.attr[:size] = div(w, 10), div(h, 20)
plt.attr[:color_palette] = [RGB(0,0,0)]
nothing
# plt
end
# function _series_added(plt::Plot{UnicodePlotsBackend}, series::Series)
# d = series.d
# # TODO don't need these once the "bar" series recipe is done
# if d[:seriestype] in (:sticks, :bar)
# d = barHack(; d...)
# elseif d[:seriestype] == :histogram
# d = barHack(; histogramHack(; d...)...)
# end
# # push!(plt.seriesargs, d)
# # plt
# end
#
#
# function _update_plot_object(plt::Plot{UnicodePlotsBackend}, d::KW)
# for k in (:title, :xguide, :yguide, :xlims, :ylims)
# if haskey(d, k)
# plt.attr[k] = d[k]
# end
# end
# end
# -------------------------------
# since this is such a hack, it's only callable using `png`... should error during normal `writemime`
function png(plt::AbstractPlot{UnicodePlotsBackend}, fn::AbstractString)
fn = addExtension(fn, "png")
fn = addExtension(fn, "png")
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
# make some whitespace and show the plot
println("\n\n\n\n\n\n")
gui(plt)
# @osx_only begin
@compat @static if is_apple()
# BEGIN HACK
# @osx_only begin
@compat @static if is_apple()
# BEGIN HACK
# wait while the plot gets drawn
sleep(0.5)
# wait while the plot gets drawn
sleep(0.5)
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
run(`screencapture -R50,600,700,420 $fn`)
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
run(`screencapture -R50,600,700,420 $fn`)
# END HACK (phew)
return
end
# END HACK (phew)
return
end
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
end
# -------------------------------
# we don't do very much for subplots... just stack them vertically
# function _create_subplot(subplt::Subplot{UnicodePlotsBackend}, isbefore::Bool)
# isbefore && return false
# true
# end
function _display(plt::Plot{UnicodePlotsBackend})
function _update_plot_object(plt::Plot{UnicodePlotsBackend})
w, h = plt[:size]
plt.attr[:size] = div(w, 10), div(h, 20)
plt.attr[:color_palette] = [RGB(0,0,0)]
rebuildUnicodePlot!(plt)
end
function _writemime(io::IO, ::MIME"text/plain", plt::Plot{UnicodePlotsBackend})
map(show, plt.o)
nothing
end
function _display(plt::Plot{UnicodePlotsBackend})
map(show, plt.o)
nothing
end
# function Base.display(::PlotsDisplay, subplt::Subplot{UnicodePlotsBackend})
# for plt in subplt.plts
# gui(plt)
# end
# end
+2
View File
@@ -479,6 +479,8 @@ function build_layout(layout::GridLayout, n::Integer)
append!(subplots, sps)
merge!(spmap, m)
i += length(sps)
elseif isa(l, Subplot)
error("Subplot exists. Cannot re-use existing layout. Please make a new one.")
end
i >= n && break # only add n subplots
end
+5 -1
View File
@@ -119,11 +119,13 @@ const _mimeformats = Dict(
"application/pdf" => "pdf",
"image/png" => "png",
"application/postscript" => "ps",
"image/svg+xml" => "svg"
"image/svg+xml" => "svg",
"text/plain" => "txt",
)
const _best_html_output_type = KW(
:pyplot => :png,
:unicodeplots => :txt,
)
# a backup for html... passes to svg or png depending on the html_output_format arg
@@ -138,6 +140,8 @@ function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
elseif output_type == :svg
# info("writing svg to html output")
writemime(io, MIME("image/svg+xml"), plt)
elseif output_type == :txt
writemime(io, MIME("text/plain"), plt)
else
error("only png or svg allowed. got: $output_type")
end
+43 -19
View File
@@ -172,6 +172,11 @@ function _apply_series_recipe(plt::Plot, d::KW)
sp_idx = get_subplot_index(plt, sp)
_update_subplot_args(plt, sp, d, sp_idx)
# do we want to override the series type?
if !is3d(st) && d[:z] != nothing && (size(d[:x]) == size(d[:y]) == size(d[:z]))
st = d[:seriestype] = (st == :scatter ? :scatter3d : :path3d)
end
# change to a 3d projection for this subplot?
if is3d(st)
sp.attr[:projection] = "3d"
@@ -183,6 +188,18 @@ function _apply_series_recipe(plt::Plot, d::KW)
sp.attr[:init] = true
end
# strip out series annotations (those which are based on series x/y coords)
# and add them to the subplot attr
sp_anns = annotations(sp[:annotations])
anns = annotations(pop!(d, :series_annotations, []))
if length(anns) > 0
x, y = d[:x], d[: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)
# adjust extrema and discrete info
if st == :image
w, h = size(d[:z])
@@ -272,7 +289,12 @@ function _plot!(plt::Plot, d::KW, args...)
# map marker_z if it's a Function
if isa(get(kw, :marker_z, nothing), Function)
# TODO: should this take y and/or z as arguments?
kw[:marker_z] = map(kw[:marker_z], kw[:x])
kw[:marker_z] = map(kw[:marker_z], kw[:x], kw[:y], kw[:z])
end
# map line_z if it's a Function
if isa(get(kw, :line_z, nothing), Function)
kw[:line_z] = map(kw[:line_z], kw[:x], kw[:y], kw[:z])
end
# convert a ribbon into a fillrange
@@ -315,9 +337,6 @@ function _plot!(plt::Plot, d::KW, args...)
:label => "",
:primary => false,
)))
# don't allow something else to handle it
d[:smooth] = false
end
else
@@ -327,6 +346,9 @@ function _plot!(plt::Plot, d::KW, args...)
end
end
# don't allow something else to handle it
d[:smooth] = false
# merge in anything meant for plot/subplot/axis
for kw in kw_list
for (k,v) in kw
@@ -383,13 +405,15 @@ function _plot!(plt::Plot, d::KW, args...)
# we'll keep a map of subplot to an attribute override dict.
# any series which belong to that subplot
sp_attrs = Dict{Subplot,Any}()
for (i,kw) in enumerate(kw_list)
for kw in kw_list
# get the Subplot object to which the series belongs
sp = get(kw, :subplot, :auto)
command_idx = kw[:series_plotindex] - kw_list[1][:series_plotindex] + 1
sp = if sp == :auto
mod1(i,length(plt.subplots))
cycle(plt.subplots, command_idx)
# mod1(command_idx, length(plt.subplots))
else
slice_arg(sp, i)
slice_arg(sp, command_idx)
end
sp = kw[:subplot] = get_subplot(plt, sp)
# idx = get_subplot_index(plt, sp)
@@ -430,7 +454,7 @@ function _plot!(plt::Plot, d::KW, args...)
# this is it folks!
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
for (i,kw) in enumerate(kw_list)
for kw in kw_list
command_idx = kw[:series_plotindex] - kw_list[1][:series_plotindex] + 1
# # get the Subplot object to which the series belongs
@@ -444,17 +468,17 @@ function _plot!(plt::Plot, d::KW, args...)
sp = kw[:subplot]
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[: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)
# # strip out series annotations (those which are based on series x/y coords)
# # and add them to the subplot attr
# sp_anns = annotations(sp[: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
_update_subplot_args(plt, sp, kw, idx)
+107 -36
View File
@@ -338,6 +338,74 @@ end
@deps sticks path scatter
# ---------------------------------------------------------------------------
# bezier curves
# get the value of the curve point at position t
function bezier_value(pts::AVec, t::Real)
val = 0.0
n = length(pts)-1
for (i,p) in enumerate(pts)
val += p * binomial(n, i-1) * (1-t)^(n-i+1) * t^(i-1)
end
val
end
# create segmented bezier curves in place of line segments
@recipe function f(::Type{Val{:curves}}, x, y, z)
args = z != nothing ? (x,y,z) : (x,y)
newx, newy = zeros(0), zeros(0)
fr = d[:fillrange]
newfr = fr != nothing ? zeros(0) : nothing
newz = z != nothing ? zeros(0) : nothing
lz = d[:line_z]
newlz = lz != nothing ? zeros(0) : nothing
npoints = pop!(d, :npoints, 30)
# for each line segment (point series with no NaNs), convert it into a bezier curve
# where the points are the control points of the curve
for rng in iter_segments(args...)
length(rng) < 2 && continue
ts = linspace(0, 1, npoints)
nanappend!(newx, map(t -> bezier_value(cycle(x,rng), t), ts))
nanappend!(newy, map(t -> bezier_value(cycle(y,rng), t), ts))
if z != nothing
nanappend!(newz, map(t -> bezier_value(cycle(z,rng), t), ts))
end
if fr != nothing
nanappend!(newfr, map(t -> bezier_value(cycle(fr,rng), t), ts))
end
if lz != nothing
lzrng = cycle(lz, rng) # the line_z's for this segment
# @show lzrng, sizeof(lzrng) map(t -> 1+floor(Int, t * (length(rng)-1)), ts)
# choose the line_z value of the control point just before this t
push!(newlz, 0.0)
append!(newlz, map(t -> lzrng[1+floor(Int, t * (length(rng)-1))], ts))
# lzrng = vcat()
# nanappend!(newlz, #map(t -> bezier_value(cycle(lz,rng), t), ts))
end
end
x := newx
y := newy
if z == nothing
seriestype := :path
else
seriestype := :path3d
z := newz
end
if fr != nothing
fillrange := newfr
end
if lz != nothing
line_z := newlz
linecolor := (isa(d[:linecolor], ColorGradient) ? d[:linecolor] : default_gradient())
end
# Plots.DD(d)
()
end
@deps curves path
# ---------------------------------------------------------------------------
# create a bar plot as a filled step function
@@ -971,6 +1039,9 @@ end
# -------------------------------------------------
# TODO: everything below here should be either changed to a
# series recipe or moved to PlotRecipes
"Sparsity plot... heatmap of non-zero values of a matrix"
function spy{T<:Real}(z::AMat{T}; kw...)
@@ -1032,56 +1103,56 @@ end
curvecolor(value, min, max, grad) = getColorZ(grad, (value-min)/(max-min))
"Plots a clockwise arc, from source to destiny, colored by weight"
function arc!(source, destiny, weight, min, max, grad)
radius = (destiny - source) / 2
arc = Plots.partialcircle(0, π, 30, radius)
x, y = Plots.unzip(arc)
plot!(x .+ radius .+ source, y, line = (curvecolor(weight, min, max, grad), 0.5, 2), legend=false)
end
# "Plots a clockwise arc, from source to destiny, colored by weight"
# function arc!(source, destiny, weight, min, max, grad)
# radius = (destiny - source) / 2
# arc = Plots.partialcircle(0, π, 30, radius)
# x, y = Plots.unzip(arc)
# plot!(x .+ radius .+ source, y, line = (curvecolor(weight, min, max, grad), 0.5, 2), legend=false)
# end
"""
`arcdiagram(source, destiny, weight[, grad])`
# """
# `arcdiagram(source, destiny, weight[, grad])`
Plots an arc diagram, form `source` to `destiny` (clockwise), using `weight` to determine the colors.
"""
function arcdiagram(source, destiny, weight; kargs...)
# Plots an arc diagram, form `source` to `destiny` (clockwise), using `weight` to determine the colors.
# """
# function arcdiagram(source, destiny, weight; kargs...)
args = KW(kargs)
grad = pop!(args, :grad, ColorGradient([colorant"darkred", colorant"darkblue"]))
# args = KW(kargs)
# grad = pop!(args, :grad, ColorGradient([colorant"darkred", colorant"darkblue"]))
if length(source) == length(destiny) == length(weight)
# if length(source) == length(destiny) == length(weight)
vertices = unique(vcat(source, destiny))
sort!(vertices)
# vertices = unique(vcat(source, destiny))
# sort!(vertices)
xmin, xmax = extrema(vertices)
plot(xlim=(xmin - 0.5, xmax + 0.5), legend=false)
# xmin, xmax = extrema(vertices)
# plot(xlim=(xmin - 0.5, xmax + 0.5), legend=false)
wmin,wmax = extrema(weight)
# wmin,wmax = extrema(weight)
for (i, j, value) in zip(source,destiny,weight)
arc!(i, j, value, wmin, wmax, grad)
end
# for (i, j, value) in zip(source,destiny,weight)
# arc!(i, j, value, wmin, wmax, grad)
# end
scatter!(vertices, zeros(length(vertices)); legend=false, args...)
# scatter!(vertices, zeros(length(vertices)); legend=false, args...)
else
# else
throw(ArgumentError("source, destiny and weight should have the same length"))
# throw(ArgumentError("source, destiny and weight should have the same length"))
end
end
# end
# end
"""
`arcdiagram(mat[, grad])`
# """
# `arcdiagram(mat[, grad])`
Plots an arc diagram from an adjacency matrix, form rows to columns (clockwise),
using the values on the matrix as weights to determine the colors.
Doesn't show edges with value zero if the input is sparse.
For simmetric matrices, only the upper triangular values are used.
"""
arcdiagram{T}(mat::AbstractArray{T,2}; kargs...) = arcdiagram(mat2list(mat)...; kargs...)
# Plots an arc diagram from an adjacency matrix, form rows to columns (clockwise),
# using the values on the matrix as weights to determine the colors.
# Doesn't show edges with value zero if the input is sparse.
# For simmetric matrices, only the upper triangular values are used.
# """
# arcdiagram{T}(mat::AbstractArray{T,2}; kargs...) = arcdiagram(mat2list(mat)...; kargs...)
# ---------------------------------------------------------------------------
# Chord diagram
+12 -12
View File
@@ -292,22 +292,22 @@ end
# # 3d line or scatter
@recipe function f(x::AVec, y::AVec, z::AVec)
st = get(d, :seriestype, :none)
if st == :scatter
d[:seriestype] = :scatter3d
elseif !is3d(st)
d[:seriestype] = :path3d
end
# st = get(d, :seriestype, :none)
# if st == :scatter
# d[:seriestype] = :scatter3d
# elseif !is3d(st)
# d[:seriestype] = :path3d
# end
SliceIt, x, y, z
end
@recipe function f(x::AMat, y::AMat, z::AMat)
st = get(d, :seriestype, :none)
if size(x) == size(y) == size(z)
if !is3d(st)
seriestype := :path3d
end
end
# st = get(d, :seriestype, :none)
# if size(x) == size(y) == size(z)
# if !is3d(st)
# seriestype := :path3d
# end
# end
SliceIt, x, y, z
end
+51
View File
@@ -136,6 +136,53 @@ function imageHack(d::KW)
d[:z], d[:fillcolor] = replace_image_with_heatmap(d[:z].surf)
end
# ---------------------------------------------------------------
# -----------------------------------------------------
# helper to manage NaN-separated segments
type SegmentsIterator
args::Tuple
nextidx::Int
n::Int
end
function iter_segments(args...)
tup = Plots.wraptuple(args)
n = maximum(map(length, tup))
SegmentsIterator(tup, 0, n)
end
# helpers to figure out if there are NaN values in a list of array types
anynan(i::Int, args...) = any(a -> !isfinite(cycle(a,i)), args)
anynan(istart::Int, iend::Int, args...) = any(i -> anynan(i, args...), istart:iend)
allnan(istart::Int, iend::Int, args...) = all(i -> anynan(i, args...), istart:iend)
Base.start(itr::SegmentsIterator) = (itr.nextidx = 1) #resets
Base.done(itr::SegmentsIterator, unused::Int) = itr.nextidx > itr.n
function Base.next(itr::SegmentsIterator, unused::Int)
i = istart = iend = itr.nextidx
# find the next NaN, and iend is the one before
while i <= itr.n + 1
if i > itr.n || anynan(i, itr.args...)
# done... array end or found NaN
iend = i-1
break
end
i += 1
end
# find the next non-NaN, and set itr.nextidx
while i <= itr.n
if !anynan(i, itr.args...)
break
end
i += 1
end
itr.nextidx = i
istart:iend, 0
end
# ------------------------------------------------------------------------------------
@@ -146,6 +193,10 @@ Base.cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
Base.cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
Base.cycle(v, idx::Int) = v
Base.cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
Base.cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
Base.cycle(v, idx::AVec{Int}) = v
makevec(v::AVec) = v
makevec{T}(v::T) = T[v]
+1 -1
View File
@@ -22,7 +22,7 @@ default(size=(500,300))
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
const _current_plots_version = v"0.7.1"
const _current_plots_version = v"0.7.2"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)