Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3544dc826 | |||
| b0bc68ae8a | |||
| c38e947dc6 | |||
| ec826fc8ce | |||
| e5c4f782a5 | |||
| a5ddebf44d | |||
| 38804898c5 | |||
| 2bd67f3519 | |||
| c8ed611c9c | |||
| 3d7d8caa82 | |||
| f64108523c | |||
| a7493504ed | |||
| bc5293b5a4 |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user