Merge branch 'master' into tryToFixIJulia
This commit is contained in:
commit
ac192ac5e9
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ examples/.ipynb_checkpoints/*
|
|||||||
examples/meetup/.ipynb_checkpoints/*
|
examples/meetup/.ipynb_checkpoints/*
|
||||||
deps/plotly-latest.min.js
|
deps/plotly-latest.min.js
|
||||||
deps/build.log
|
deps/build.log
|
||||||
|
deps/deps.jl
|
||||||
|
|||||||
38
NEWS.md
38
NEWS.md
@ -10,7 +10,43 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
## (current master)
|
## (current master)
|
||||||
- All new development should target Julia 1.x!
|
|
||||||
|
## 0.22.1
|
||||||
|
- push PlotsDisplay just after REPLDisplay
|
||||||
|
|
||||||
|
## 0.22.0
|
||||||
|
- deprecate GLVisualize
|
||||||
|
- allow 1-row and 1-column heatmaps
|
||||||
|
- add portfoliodecomposition recipe from PlotRecipes
|
||||||
|
- solve Shape bug
|
||||||
|
- simplify PyPlot backend installation
|
||||||
|
- fix wireframe bug in PyPlot
|
||||||
|
- fix color bug in PyPlot
|
||||||
|
- minor bug fixes in gr and pyplot
|
||||||
|
|
||||||
|
## 0.21.0
|
||||||
|
- Compatibility with StaticArrays 0.9.0
|
||||||
|
- Up GR min version to 0.35
|
||||||
|
- fix :mirror
|
||||||
|
|
||||||
|
## 0.20.6
|
||||||
|
- fixes for PlotDocs.jl
|
||||||
|
- fix gr axis color argument
|
||||||
|
- Shapes for inspectdr
|
||||||
|
- don't load plotly js file by default
|
||||||
|
|
||||||
|
## 0.20.5
|
||||||
|
- fix precompilation issue when depending on Plots
|
||||||
|
|
||||||
|
## 0.20.4
|
||||||
|
- honour `html_output_format` in Juno
|
||||||
|
|
||||||
|
## 0.20.3
|
||||||
|
- implement guide position in gr, pyplot and pgfplots
|
||||||
|
- inspectdr fixes
|
||||||
|
- default appveyor
|
||||||
|
- rudimentary missings support
|
||||||
|
- deprecation fixes for PGFPlots
|
||||||
|
|
||||||
## 0.20.0
|
## 0.20.0
|
||||||
Many updates, min julia 1.0
|
Many updates, min julia 1.0
|
||||||
|
|||||||
2
REQUIRE
2
REQUIRE
@ -13,4 +13,4 @@ JSON
|
|||||||
NaNMath
|
NaNMath
|
||||||
Requires
|
Requires
|
||||||
Contour
|
Contour
|
||||||
GR 0.34.0
|
GR 0.35.0
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- julia_version: 0.7
|
# - julia_version: 0.7
|
||||||
- julia_version: 1
|
- julia_version: 1
|
||||||
- julia_version: nightly
|
- julia_version: nightly
|
||||||
|
|
||||||
|
|||||||
20
deps/build.jl
vendored
20
deps/build.jl
vendored
@ -1,8 +1,18 @@
|
|||||||
|
|
||||||
#TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist
|
#TODO: download https://cdn.plot.ly/plotly-latest.min.js to deps/ if it doesn't exist
|
||||||
|
file_path = ""
|
||||||
local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js")
|
if get(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL", "false") == "true"
|
||||||
if !isfile(local_fn)
|
global file_path
|
||||||
@info("Cannot find deps/plotly-latest.min.js... downloading latest version.")
|
local_fn = joinpath(dirname(@__FILE__), "plotly-latest.min.js")
|
||||||
download("https://cdn.plot.ly/plotly-latest.min.js", local_fn)
|
if !isfile(local_fn)
|
||||||
|
@info("Cannot find deps/plotly-latest.min.js... downloading latest version.")
|
||||||
|
download("https://cdn.plot.ly/plotly-latest.min.js", local_fn)
|
||||||
|
isfile(local_fn) && (file_path = local_fn)
|
||||||
|
else
|
||||||
|
file_path = local_fn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
open("deps.jl", "w") do io
|
||||||
|
println(io, "const plotly_local_file_path = $(repr(file_path))")
|
||||||
end
|
end
|
||||||
|
|||||||
18
src/Plots.jl
18
src/Plots.jl
@ -1,9 +1,10 @@
|
|||||||
module Plots
|
module Plots
|
||||||
|
|
||||||
|
_current_plots_version = v"0.20.6"
|
||||||
|
|
||||||
using Reexport
|
using Reexport
|
||||||
|
|
||||||
import StaticArrays
|
import StaticArrays
|
||||||
using StaticArrays.FixedSizeArrays
|
|
||||||
using Dates, Printf, Statistics, Base64, LinearAlgebra
|
using Dates, Printf, Statistics, Base64, LinearAlgebra
|
||||||
import SparseArrays: findnz
|
import SparseArrays: findnz
|
||||||
|
|
||||||
@ -18,6 +19,17 @@ import JSON
|
|||||||
|
|
||||||
using Requires
|
using Requires
|
||||||
|
|
||||||
|
if isfile(joinpath(@__DIR__, "..", "deps", "deps.jl"))
|
||||||
|
include(joinpath(@__DIR__, "..", "deps", "deps.jl"))
|
||||||
|
else
|
||||||
|
# This is a bit dirty, but I don't really see why anyone should be forced
|
||||||
|
# to build Plots, while it will just include exactly the below line
|
||||||
|
# as long as `ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] = "true"` is not set.
|
||||||
|
# If the above env is set + `plotly_local_file_path == ""``,
|
||||||
|
# it will warn in the __init__ function to run build
|
||||||
|
const plotly_local_file_path = ""
|
||||||
|
end
|
||||||
|
|
||||||
export
|
export
|
||||||
grid,
|
grid,
|
||||||
bbox,
|
bbox,
|
||||||
@ -170,6 +182,10 @@ include("backends.jl")
|
|||||||
include("output.jl")
|
include("output.jl")
|
||||||
include("init.jl")
|
include("init.jl")
|
||||||
|
|
||||||
|
include("backends/plotly.jl")
|
||||||
|
include("backends/gr.jl")
|
||||||
|
include("backends/web.jl")
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
@shorthands scatter
|
@shorthands scatter
|
||||||
|
|||||||
@ -117,7 +117,7 @@ const _arg_desc = KW(
|
|||||||
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
|
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
|
||||||
:rotation => "Number. Degrees rotation of tick labels.",
|
:rotation => "Number. Degrees rotation of tick labels.",
|
||||||
:flip => "Bool. Should we flip (reverse) the axis?",
|
:flip => "Bool. Should we flip (reverse) the axis?",
|
||||||
:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.",
|
:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
|
||||||
:tickfontfamily => "String or Symbol. Font family of tick labels.",
|
:tickfontfamily => "String or Symbol. Font family of tick labels.",
|
||||||
:tickfontsize => "Integer. Font pointsize of tick labels.",
|
:tickfontsize => "Integer. Font pointsize of tick labels.",
|
||||||
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
|
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
|
||||||
|
|||||||
388
src/backends.jl
388
src/backends.jl
@ -149,7 +149,7 @@ function pickDefaultBackend()
|
|||||||
@warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.")
|
@warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t",
|
@warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" *
|
||||||
join(sort(_backends), "\n\t"))
|
join(sort(_backends), "\n\t"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -157,7 +157,7 @@ function pickDefaultBackend()
|
|||||||
# the ordering/inclusion of this package list is my semi-arbitrary guess at
|
# the ordering/inclusion of this package list is my semi-arbitrary guess at
|
||||||
# which one someone will want to use if they have the package installed...accounting for
|
# which one someone will want to use if they have the package installed...accounting for
|
||||||
# features, speed, and robustness
|
# features, speed, and robustness
|
||||||
# for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR", "GLVisualize")
|
# for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR")
|
||||||
# if pkgstr in keys(Pkg.installed())
|
# if pkgstr in keys(Pkg.installed())
|
||||||
# return backend(Symbol(lowercase(pkgstr)))
|
# return backend(Symbol(lowercase(pkgstr)))
|
||||||
# end
|
# end
|
||||||
@ -213,11 +213,11 @@ function backend(sym::Symbol)
|
|||||||
backend()
|
backend()
|
||||||
end
|
end
|
||||||
|
|
||||||
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse]
|
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize]
|
||||||
|
|
||||||
function warn_on_deprecated_backend(bsym::Symbol)
|
function warn_on_deprecated_backend(bsym::Symbol)
|
||||||
if bsym in _deprecated_backends
|
if bsym in _deprecated_backends
|
||||||
@warn("Backend $bsym has been deprecated. It may not work as originally intended.")
|
@warn("Backend $bsym has been deprecated.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -268,17 +268,11 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# @init_backend Immerse
|
|
||||||
# @init_backend Gadfly
|
|
||||||
@init_backend PyPlot
|
@init_backend PyPlot
|
||||||
# @init_backend Qwt
|
|
||||||
@init_backend UnicodePlots
|
@init_backend UnicodePlots
|
||||||
# @init_backend Winston
|
|
||||||
# @init_backend Bokeh
|
|
||||||
@init_backend Plotly
|
@init_backend Plotly
|
||||||
@init_backend PlotlyJS
|
@init_backend PlotlyJS
|
||||||
@init_backend GR
|
@init_backend GR
|
||||||
@init_backend GLVisualize
|
|
||||||
@init_backend PGFPlots
|
@init_backend PGFPlots
|
||||||
@init_backend InspectDR
|
@init_backend InspectDR
|
||||||
@init_backend HDF5
|
@init_backend HDF5
|
||||||
@ -331,34 +325,127 @@ function add_backend_string(pkg::AbstractBackend)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# glvisualize
|
# gr
|
||||||
|
|
||||||
function _initialize_backend(::GLVisualizeBackend; kw...)
|
const _gr_attr = merge_with_base_supported([
|
||||||
@eval Main begin
|
:annotations,
|
||||||
import GLVisualize, GeometryTypes, Reactive, GLAbstraction, GLWindow, Contour
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
import GeometryTypes: Point2f0, Point3f0, Vec2f0, Vec3f0, GLNormalMesh, SimpleRectangle, Point, Vec
|
:foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
|
||||||
import FileIO, Images
|
:foreground_color_text, :foreground_color_border,
|
||||||
export GLVisualize
|
:label,
|
||||||
import Reactive: Signal
|
:seriescolor, :seriesalpha,
|
||||||
import GLAbstraction: Style
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
import GLVisualize: visualize
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
import Plots.GL
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
||||||
import UnicodeFun
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
end
|
:bins,
|
||||||
|
:layout,
|
||||||
|
:title, :window_title,
|
||||||
|
:guide, :lims, :ticks, :scale, :flip,
|
||||||
|
:match_dimensions,
|
||||||
|
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
||||||
|
:titlefontrotation, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign,
|
||||||
|
:legendfontrotation, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign,
|
||||||
|
:tickfontrotation, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
|
||||||
|
:guidefontrotation, :guidefontcolor,
|
||||||
|
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
||||||
|
:legend, :legendtitle, :colorbar, :colorbar_title,
|
||||||
|
:fill_z, :line_z, :marker_z, :levels,
|
||||||
|
:ribbon, :quiver,
|
||||||
|
:orientation,
|
||||||
|
:overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
:aspect_ratio,
|
||||||
|
:normalize, :weights,
|
||||||
|
:inset_subplots,
|
||||||
|
:bar_width,
|
||||||
|
:arrow,
|
||||||
|
:framestyle,
|
||||||
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
|
:contour_labels,
|
||||||
|
])
|
||||||
|
const _gr_seriestype = [
|
||||||
|
:path, :scatter, :straightline,
|
||||||
|
:heatmap, :pie, :image,
|
||||||
|
:contour, :path3d, :scatter3d, :surface, :wireframe,
|
||||||
|
:shape
|
||||||
|
]
|
||||||
|
const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||||
|
const _gr_marker = _allMarkers
|
||||||
|
const _gr_scale = [:identity, :log10]
|
||||||
|
is_marker_supported(::GRBackend, shape::Shape) = true
|
||||||
|
|
||||||
|
function add_backend_string(::GRBackend)
|
||||||
|
"""
|
||||||
|
Pkg.add("GR")
|
||||||
|
Pkg.build("GR")
|
||||||
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# hdf5
|
# plotly
|
||||||
|
|
||||||
function _initialize_backend(::HDF5Backend)
|
const _plotly_attr = merge_with_base_supported([
|
||||||
@eval Main begin
|
:annotations,
|
||||||
import HDF5
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
export HDF5
|
:foreground_color_legend, :foreground_color_guide,
|
||||||
end
|
:foreground_color_grid, :foreground_color_axis,
|
||||||
end
|
:foreground_color_text, :foreground_color_border,
|
||||||
|
:foreground_color_title,
|
||||||
|
:label,
|
||||||
|
:seriescolor, :seriesalpha,
|
||||||
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
||||||
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
|
:bins,
|
||||||
|
:title, :title_location,
|
||||||
|
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
||||||
|
:titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
|
:window_title,
|
||||||
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
|
:tickfont, :guidefont, :legendfont,
|
||||||
|
:grid, :gridalpha, :gridlinewidth,
|
||||||
|
:legend, :colorbar, :colorbar_title,
|
||||||
|
:marker_z, :fill_z, :line_z, :levels,
|
||||||
|
:ribbon, :quiver,
|
||||||
|
:orientation,
|
||||||
|
# :overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
:normalize, :weights,
|
||||||
|
# :contours,
|
||||||
|
:aspect_ratio,
|
||||||
|
:hover,
|
||||||
|
:inset_subplots,
|
||||||
|
:bar_width,
|
||||||
|
:clims,
|
||||||
|
:framestyle,
|
||||||
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
|
:contour_labels,
|
||||||
|
])
|
||||||
|
|
||||||
|
const _plotly_seriestype = [
|
||||||
|
:path, :scatter, :pie, :heatmap,
|
||||||
|
:contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl,
|
||||||
|
:straightline
|
||||||
|
]
|
||||||
|
const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot]
|
||||||
|
const _plotly_marker = [
|
||||||
|
:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle,
|
||||||
|
:cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline
|
||||||
|
]
|
||||||
|
const _plotly_scale = [:identity, :log10]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# PGFPLOTS
|
# pgfplots
|
||||||
|
|
||||||
function add_backend_string(::PGFPlotsBackend)
|
function add_backend_string(::PGFPlotsBackend)
|
||||||
"""
|
"""
|
||||||
@ -368,26 +455,78 @@ function add_backend_string(::PGFPlotsBackend)
|
|||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
const _pgfplots_attr = merge_with_base_supported([
|
||||||
|
:annotations,
|
||||||
|
:background_color_legend,
|
||||||
|
:background_color_inside,
|
||||||
|
# :background_color_outside,
|
||||||
|
# :foreground_color_legend,
|
||||||
|
:foreground_color_grid, :foreground_color_axis,
|
||||||
|
:foreground_color_text, :foreground_color_border,
|
||||||
|
:label,
|
||||||
|
:seriescolor, :seriesalpha,
|
||||||
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
||||||
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
|
:bins,
|
||||||
|
# :bar_width, :bar_edges,
|
||||||
|
:title,
|
||||||
|
# :window_title,
|
||||||
|
:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
|
:tickfont, :guidefont, :legendfont,
|
||||||
|
:grid, :legend,
|
||||||
|
:colorbar, :colorbar_title,
|
||||||
|
:fill_z, :line_z, :marker_z, :levels,
|
||||||
|
# :ribbon, :quiver, :arrow,
|
||||||
|
# :orientation,
|
||||||
|
# :overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
# :normalize, :weights, :contours,
|
||||||
|
:aspect_ratio,
|
||||||
|
# :match_dimensions,
|
||||||
|
:tick_direction,
|
||||||
|
:framestyle,
|
||||||
|
:camera,
|
||||||
|
:contour_labels,
|
||||||
|
])
|
||||||
|
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
|
||||||
|
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||||
|
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
|
||||||
|
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# plotlyjs
|
# plotlyjs
|
||||||
|
|
||||||
|
function _initialize_backend(pkg::PlotlyJSBackend)
|
||||||
|
sym = backend_package_name(pkg)
|
||||||
|
@eval Main begin
|
||||||
|
import PlotlyJS, ORCA
|
||||||
|
export PlotlyJS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function add_backend_string(::PlotlyJSBackend)
|
function add_backend_string(::PlotlyJSBackend)
|
||||||
"""
|
"""
|
||||||
using Pkg
|
using Pkg
|
||||||
Pkg.add("PlotlyJS")
|
Pkg.add(["PlotlyJS", "Blink", "ORCA"])
|
||||||
Pkg.add("Rsvg")
|
|
||||||
import Blink
|
import Blink
|
||||||
Blink.AtomShell.install()
|
Blink.AtomShell.install()
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
const _plotlyjs_attr = _plotly_attr
|
||||||
|
const _plotlyjs_seriestype = _plotly_seriestype
|
||||||
|
const _plotlyjs_style = _plotly_style
|
||||||
|
const _plotlyjs_marker = _plotly_marker
|
||||||
|
const _plotlyjs_scale = _plotly_scale
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# pyplot
|
# pyplot
|
||||||
|
|
||||||
function _initialize_backend(::PyPlotBackend)
|
function _initialize_backend(::PyPlotBackend)
|
||||||
@eval Main begin
|
@eval Main begin
|
||||||
import PyPlot, PyCall
|
import PyPlot
|
||||||
import LaTeXStrings
|
|
||||||
|
|
||||||
export PyPlot
|
export PyPlot
|
||||||
|
|
||||||
@ -399,18 +538,66 @@ end
|
|||||||
function add_backend_string(::PyPlotBackend)
|
function add_backend_string(::PyPlotBackend)
|
||||||
"""
|
"""
|
||||||
using Pkg
|
using Pkg
|
||||||
Pkg.add("PyPlot")
|
|
||||||
Pkg.add("PyCall")
|
|
||||||
Pkg.add("LaTeXStrings")
|
|
||||||
withenv("PYTHON" => "") do
|
withenv("PYTHON" => "") do
|
||||||
Pkg.build("PyCall")
|
Pkg.add("PyPlot")
|
||||||
Pkg.build("PyPlot")
|
Pkg.build("PyPlot")
|
||||||
end
|
end
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
const _pyplot_attr = merge_with_base_supported([
|
||||||
|
:annotations,
|
||||||
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
|
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
|
||||||
|
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
||||||
|
:label,
|
||||||
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
||||||
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
|
:bins, :bar_width, :bar_edges, :bar_position,
|
||||||
|
:title, :title_location, :titlefont,
|
||||||
|
:window_title,
|
||||||
|
:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
|
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
|
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
||||||
|
:legend, :legendtitle, :colorbar,
|
||||||
|
:marker_z, :line_z, :fill_z,
|
||||||
|
:levels,
|
||||||
|
:ribbon, :quiver, :arrow,
|
||||||
|
:orientation,
|
||||||
|
:overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
:normalize, :weights,
|
||||||
|
:contours, :aspect_ratio,
|
||||||
|
:match_dimensions,
|
||||||
|
:clims,
|
||||||
|
:inset_subplots,
|
||||||
|
:dpi,
|
||||||
|
:colorbar_title,
|
||||||
|
:stride,
|
||||||
|
:framestyle,
|
||||||
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
|
:contour_labels,
|
||||||
|
])
|
||||||
|
const _pyplot_seriestype = [
|
||||||
|
:path, :steppre, :steppost, :shape, :straightline,
|
||||||
|
:scatter, :hexbin, #:histogram2d, :histogram,
|
||||||
|
# :bar,
|
||||||
|
:heatmap, :pie, :image,
|
||||||
|
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
|
||||||
|
]
|
||||||
|
const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot]
|
||||||
|
const _pyplot_marker = vcat(_allMarkers, :pixel)
|
||||||
|
const _pyplot_scale = [:identity, :ln, :log2, :log10]
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# unicodeplots
|
# unicodeplots
|
||||||
|
|
||||||
function add_backend_string(::UnicodePlotsBackend)
|
function add_backend_string(::UnicodePlotsBackend)
|
||||||
"""
|
"""
|
||||||
using Pkg
|
using Pkg
|
||||||
@ -418,3 +605,126 @@ function add_backend_string(::UnicodePlotsBackend)
|
|||||||
Pkg.build("UnicodePlots")
|
Pkg.build("UnicodePlots")
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
const _unicodeplots_attr = merge_with_base_supported([
|
||||||
|
:label,
|
||||||
|
:legend,
|
||||||
|
:seriescolor,
|
||||||
|
:seriesalpha,
|
||||||
|
:linestyle,
|
||||||
|
:markershape,
|
||||||
|
:bins,
|
||||||
|
:title,
|
||||||
|
:guide, :lims,
|
||||||
|
])
|
||||||
|
const _unicodeplots_seriestype = [
|
||||||
|
:path, :scatter, :straightline,
|
||||||
|
# :bar,
|
||||||
|
:shape,
|
||||||
|
:histogram2d,
|
||||||
|
:spy
|
||||||
|
]
|
||||||
|
const _unicodeplots_style = [:auto, :solid]
|
||||||
|
const _unicodeplots_marker = [:none, :auto, :circle]
|
||||||
|
const _unicodeplots_scale = [:identity]
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# hdf5
|
||||||
|
|
||||||
|
const _hdf5_attr = merge_with_base_supported([
|
||||||
|
:annotations,
|
||||||
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
|
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
|
||||||
|
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
||||||
|
:label,
|
||||||
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
||||||
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
|
:bins, :bar_width, :bar_edges, :bar_position,
|
||||||
|
:title, :title_location, :titlefont,
|
||||||
|
:window_title,
|
||||||
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
|
:tickfont, :guidefont, :legendfont,
|
||||||
|
:grid, :legend, :colorbar,
|
||||||
|
:marker_z, :line_z, :fill_z,
|
||||||
|
:levels,
|
||||||
|
:ribbon, :quiver, :arrow,
|
||||||
|
:orientation,
|
||||||
|
:overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
:normalize, :weights,
|
||||||
|
:contours, :aspect_ratio,
|
||||||
|
:match_dimensions,
|
||||||
|
:clims,
|
||||||
|
:inset_subplots,
|
||||||
|
:dpi,
|
||||||
|
:colorbar_title,
|
||||||
|
])
|
||||||
|
const _hdf5_seriestype = [
|
||||||
|
:path, :steppre, :steppost, :shape, :straightline,
|
||||||
|
:scatter, :hexbin, #:histogram2d, :histogram,
|
||||||
|
# :bar,
|
||||||
|
:heatmap, :pie, :image,
|
||||||
|
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
|
||||||
|
]
|
||||||
|
const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot]
|
||||||
|
const _hdf5_marker = vcat(_allMarkers, :pixel)
|
||||||
|
const _hdf5_scale = [:identity, :ln, :log2, :log10]
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# inspectdr
|
||||||
|
|
||||||
|
const _inspectdr_attr = merge_with_base_supported([
|
||||||
|
:annotations,
|
||||||
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
|
# :foreground_color_grid,
|
||||||
|
:foreground_color_legend, :foreground_color_title,
|
||||||
|
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
||||||
|
:label,
|
||||||
|
:seriescolor, :seriesalpha,
|
||||||
|
:linecolor, :linestyle, :linewidth, :linealpha,
|
||||||
|
:markershape, :markercolor, :markersize, :markeralpha,
|
||||||
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
||||||
|
:markerstrokestyle, #Causes warning not to have it... what is this?
|
||||||
|
:fillcolor, :fillalpha, #:fillrange,
|
||||||
|
# :bins, :bar_width, :bar_edges, :bar_position,
|
||||||
|
:title, :title_location,
|
||||||
|
:window_title,
|
||||||
|
:guide, :lims, :scale, #:ticks, :flip, :rotation,
|
||||||
|
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
|
:grid, :legend, #:colorbar,
|
||||||
|
# :marker_z,
|
||||||
|
# :line_z,
|
||||||
|
# :levels,
|
||||||
|
# :ribbon, :quiver, :arrow,
|
||||||
|
# :orientation,
|
||||||
|
:overwrite_figure,
|
||||||
|
:polar,
|
||||||
|
# :normalize, :weights,
|
||||||
|
# :contours, :aspect_ratio,
|
||||||
|
:match_dimensions,
|
||||||
|
# :clims,
|
||||||
|
# :inset_subplots,
|
||||||
|
:dpi,
|
||||||
|
# :colorbar_title,
|
||||||
|
])
|
||||||
|
const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot]
|
||||||
|
const _inspectdr_seriestype = [
|
||||||
|
:path, :scatter, :shape, :straightline, #, :steppre, :steppost
|
||||||
|
]
|
||||||
|
#see: _allMarkers, _shape_keys
|
||||||
|
const _inspectdr_marker = Symbol[
|
||||||
|
:none, :auto,
|
||||||
|
:circle, :rect, :diamond,
|
||||||
|
:cross, :xcross,
|
||||||
|
:utriangle, :dtriangle, :rtriangle, :ltriangle,
|
||||||
|
:pentagon, :hexagon, :heptagon, :octagon,
|
||||||
|
:star4, :star5, :star6, :star7, :star8,
|
||||||
|
:vline, :hline, :+, :x,
|
||||||
|
]
|
||||||
|
|
||||||
|
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,65 +3,6 @@
|
|||||||
|
|
||||||
# significant contributions by @jheinen
|
# significant contributions by @jheinen
|
||||||
|
|
||||||
const _gr_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
|
||||||
:foreground_color_legend, :foreground_color_grid, :foreground_color_axis,
|
|
||||||
:foreground_color_text, :foreground_color_border,
|
|
||||||
:label,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins,
|
|
||||||
:layout,
|
|
||||||
:title, :window_title,
|
|
||||||
:guide, :guide_position, :lims, :ticks, :scale, :flip,
|
|
||||||
:match_dimensions,
|
|
||||||
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
|
||||||
:titlefontrotation, :titlefontcolor,
|
|
||||||
:legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign,
|
|
||||||
:legendfontrotation, :legendfontcolor,
|
|
||||||
:tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign,
|
|
||||||
:tickfontrotation, :tickfontcolor,
|
|
||||||
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
|
|
||||||
:guidefontrotation, :guidefontcolor,
|
|
||||||
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
|
||||||
:legend, :legendtitle, :colorbar, :colorbar_title,
|
|
||||||
:fill_z, :line_z, :marker_z, :levels,
|
|
||||||
:ribbon, :quiver,
|
|
||||||
:orientation,
|
|
||||||
:overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
:aspect_ratio,
|
|
||||||
:normalize, :weights,
|
|
||||||
:inset_subplots,
|
|
||||||
:bar_width,
|
|
||||||
:arrow,
|
|
||||||
:framestyle,
|
|
||||||
:tick_direction,
|
|
||||||
:camera,
|
|
||||||
:contour_labels,
|
|
||||||
])
|
|
||||||
const _gr_seriestype = [
|
|
||||||
:path, :scatter, :straightline,
|
|
||||||
:heatmap, :pie, :image,
|
|
||||||
:contour, :path3d, :scatter3d, :surface, :wireframe,
|
|
||||||
:shape
|
|
||||||
]
|
|
||||||
const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
|
||||||
const _gr_marker = _allMarkers
|
|
||||||
const _gr_scale = [:identity, :log10]
|
|
||||||
is_marker_supported(::GRBackend, shape::Shape) = true
|
|
||||||
|
|
||||||
function add_backend_string(::GRBackend)
|
|
||||||
"""
|
|
||||||
Pkg.add("GR")
|
|
||||||
Pkg.build("GR")
|
|
||||||
"""
|
|
||||||
end
|
|
||||||
|
|
||||||
import GR
|
import GR
|
||||||
export GR
|
export GR
|
||||||
|
|
||||||
@ -661,11 +602,19 @@ function _update_min_padding!(sp::Subplot{GRBackend})
|
|||||||
end
|
end
|
||||||
# Add margin for x label
|
# Add margin for x label
|
||||||
if sp[:xaxis][:guide] != ""
|
if sp[:xaxis][:guide] != ""
|
||||||
bottompad += 4mm
|
if sp[:xaxis][:guide_position] == :top || (sp[:xaxis][:guide_position] == :auto && sp[:xaxis][:mirror] == true)
|
||||||
|
toppad += 4mm
|
||||||
|
else
|
||||||
|
bottompad += 4mm
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# Add margin for y label
|
# Add margin for y label
|
||||||
if sp[:yaxis][:guide] != ""
|
if sp[:yaxis][:guide] != ""
|
||||||
leftpad += 4mm
|
if sp[:yaxis][:guide_position] == :right || (sp[:yaxis][:guide_position] == :auto && sp[:yaxis][:mirror] == true)
|
||||||
|
rightpad += 4mm
|
||||||
|
else
|
||||||
|
leftpad += 4mm
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if sp[:colorbar_title] != ""
|
if sp[:colorbar_title] != ""
|
||||||
rightpad += 4mm
|
rightpad += 4mm
|
||||||
@ -722,7 +671,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
outside_ticks = true
|
outside_ticks = true
|
||||||
for ax in (sp[:xaxis], sp[:yaxis])
|
for ax in (sp[:xaxis], sp[:yaxis])
|
||||||
v = series[ax[:letter]]
|
v = series[ax[:letter]]
|
||||||
if diff(collect(extrema(diff(v))))[1] > 1e-6*std(v)
|
if length(v) > 1 && diff(collect(extrema(diff(v))))[1] > 1e-6*std(v)
|
||||||
@warn("GR: heatmap only supported with equally spaced data.")
|
@warn("GR: heatmap only supported with equally spaced data.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -855,12 +804,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
# axis lines
|
# axis lines
|
||||||
if xaxis[:showaxis]
|
if xaxis[:showaxis]
|
||||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
gr_set_line(1, :solid, xaxis[:foreground_color_border])
|
||||||
GR.setclip(0)
|
GR.setclip(0)
|
||||||
gr_polyline(coords(xspine_segs)...)
|
gr_polyline(coords(xspine_segs)...)
|
||||||
end
|
end
|
||||||
if yaxis[:showaxis]
|
if yaxis[:showaxis]
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
gr_set_line(1, :solid, yaxis[:foreground_color_border])
|
||||||
GR.setclip(0)
|
GR.setclip(0)
|
||||||
gr_polyline(coords(yspine_segs)...)
|
gr_polyline(coords(yspine_segs)...)
|
||||||
end
|
end
|
||||||
@ -962,7 +911,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
if xaxis[:guide] != ""
|
if xaxis[:guide] != ""
|
||||||
gr_set_font(guidefont(xaxis))
|
gr_set_font(guidefont(xaxis))
|
||||||
if xaxis[:guide_position] == :top
|
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||||
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
|
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
|
||||||
else
|
else
|
||||||
@ -974,7 +923,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
if yaxis[:guide] != ""
|
if yaxis[:guide] != ""
|
||||||
gr_set_font(guidefont(yaxis))
|
gr_set_font(guidefont(yaxis))
|
||||||
GR.setcharup(-1, 0)
|
GR.setcharup(-1, 0)
|
||||||
if yaxis[:guide_position] == :left
|
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||||
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
|
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
|
||||||
else
|
else
|
||||||
@ -1109,7 +1058,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
if length(x) == length(y) == length(z)
|
if length(x) == length(y) == length(z)
|
||||||
GR.trisurface(x, y, z)
|
GR.trisurface(x, y, z)
|
||||||
else
|
else
|
||||||
GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
try
|
||||||
|
GR.gr3.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
||||||
|
catch
|
||||||
|
GR.surface(x, y, z, GR.OPTION_COLORED_MESH)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
GR.setfillcolorind(0)
|
GR.setfillcolorind(0)
|
||||||
|
|||||||
@ -16,16 +16,19 @@ Read from .hdf5 file using:
|
|||||||
|
|
||||||
#==TODO
|
#==TODO
|
||||||
===============================================================================
|
===============================================================================
|
||||||
1. Support more features
|
1. Support more features.
|
||||||
- SeriesAnnotations & GridLayout known to be missing.
|
- GridLayout known not to be working.
|
||||||
3. Improve error handling.
|
2. Improve error handling.
|
||||||
- Will likely crash if file format is off.
|
- Will likely crash if file format is off.
|
||||||
2. Save data in a folder parallel to "plot".
|
3. Save data in a folder parallel to "plot".
|
||||||
- Will make it easier for users to locate data.
|
- Will make it easier for users to locate data.
|
||||||
- Use HDF5 reference to link data?
|
- Use HDF5 reference to link data?
|
||||||
3. Develop an actual versioned file format.
|
4. Develop an actual versioned file format.
|
||||||
- Should have some form of backward compatibility.
|
- Should have some form of backward compatibility.
|
||||||
- Should be reliable for archival purposes.
|
- Should be reliable for archival purposes.
|
||||||
|
5. Fix construction of plot object with hdf5plot_read.
|
||||||
|
- Not building object correctly when backends do not natively support
|
||||||
|
a certain feature (ex: :steppre)
|
||||||
==#
|
==#
|
||||||
|
|
||||||
import FixedPointNumbers: N0f8 #In core Julia
|
import FixedPointNumbers: N0f8 #In core Julia
|
||||||
@ -56,53 +59,13 @@ const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing)
|
|||||||
|
|
||||||
#Simple sub-structures that can just be written out using _hdf5plot_gwritefields:
|
#Simple sub-structures that can just be written out using _hdf5plot_gwritefields:
|
||||||
const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox,
|
const HDF5PLOT_SIMPLESUBSTRUCT = Union{Font, BoundingBox,
|
||||||
GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText
|
GridLayout, RootLayout, ColorGradient, SeriesAnnotations, PlotText,
|
||||||
|
Shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#==
|
#==
|
||||||
===============================================================================#
|
===============================================================================#
|
||||||
|
|
||||||
const _hdf5_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
|
||||||
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
|
|
||||||
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
|
||||||
:label,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins, :bar_width, :bar_edges, :bar_position,
|
|
||||||
:title, :title_location, :titlefont,
|
|
||||||
:window_title,
|
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
|
||||||
:tickfont, :guidefont, :legendfont,
|
|
||||||
:grid, :legend, :colorbar,
|
|
||||||
:marker_z, :line_z, :fill_z,
|
|
||||||
:levels,
|
|
||||||
:ribbon, :quiver, :arrow,
|
|
||||||
:orientation,
|
|
||||||
:overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
:normalize, :weights,
|
|
||||||
:contours, :aspect_ratio,
|
|
||||||
:match_dimensions,
|
|
||||||
:clims,
|
|
||||||
:inset_subplots,
|
|
||||||
:dpi,
|
|
||||||
:colorbar_title,
|
|
||||||
])
|
|
||||||
const _hdf5_seriestype = [
|
|
||||||
:path, :steppre, :steppost, :shape, :straightline,
|
|
||||||
:scatter, :hexbin, #:histogram2d, :histogram,
|
|
||||||
# :bar,
|
|
||||||
:heatmap, :pie, :image,
|
|
||||||
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
|
|
||||||
]
|
|
||||||
const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot]
|
|
||||||
const _hdf5_marker = vcat(_allMarkers, :pixel)
|
|
||||||
const _hdf5_scale = [:identity, :ln, :log2, :log10]
|
|
||||||
is_marker_supported(::HDF5Backend, shape::Shape) = true
|
is_marker_supported(::HDF5Backend, shape::Shape) = true
|
||||||
|
|
||||||
if length(HDF5PLOT_MAP_TELEM2STR) < 1
|
if length(HDF5PLOT_MAP_TELEM2STR) < 1
|
||||||
@ -125,7 +88,8 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1
|
|||||||
"GRIDLAYOUT" => GridLayout,
|
"GRIDLAYOUT" => GridLayout,
|
||||||
"ROOTLAYOUT" => RootLayout,
|
"ROOTLAYOUT" => RootLayout,
|
||||||
"SERIESANNOTATIONS" => SeriesAnnotations,
|
"SERIESANNOTATIONS" => SeriesAnnotations,
|
||||||
# "PLOTTEXT" => PlotText,
|
"PLOTTEXT" => PlotText,
|
||||||
|
"SHAPE" => Shape,
|
||||||
"COLORGRADIENT" => ColorGradient,
|
"COLORGRADIENT" => ColorGradient,
|
||||||
"AXIS" => Axis,
|
"AXIS" => Axis,
|
||||||
"SURFACE" => Surface,
|
"SURFACE" => Surface,
|
||||||
@ -284,6 +248,14 @@ end
|
|||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
function _hdf5plot_gwrite(grp, k::String, v) #Default
|
function _hdf5plot_gwrite(grp, k::String, v) #Default
|
||||||
|
T = typeof(v)
|
||||||
|
if !(T <: Number || T <: String)
|
||||||
|
tstr = string(T)
|
||||||
|
path = HDF5.name(grp) * "/" * k
|
||||||
|
@info("Type not supported: $tstr\npath: $path")
|
||||||
|
# @show v
|
||||||
|
return
|
||||||
|
end
|
||||||
grp[k] = v
|
grp[k] = v
|
||||||
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
||||||
end
|
end
|
||||||
@ -338,10 +310,6 @@ function _hdf5plot_gwrite(grp, k::String, v::Colorant)
|
|||||||
end
|
end
|
||||||
#Custom vector (when not using simple numeric type):
|
#Custom vector (when not using simple numeric type):
|
||||||
function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T
|
function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T
|
||||||
if "annotations" == k;
|
|
||||||
return #Hack. Does not yet support annotations.
|
|
||||||
end
|
|
||||||
|
|
||||||
vgrp = HDF5.g_create(grp, k)
|
vgrp = HDF5.g_create(grp, k)
|
||||||
_hdf5plot_writetype(vgrp, Array) #ANY
|
_hdf5plot_writetype(vgrp, Array) #ANY
|
||||||
sz = size(v)
|
sz = size(v)
|
||||||
@ -351,7 +319,7 @@ function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T
|
|||||||
coord = lidx[iter]
|
coord = lidx[iter]
|
||||||
elem = v[iter]
|
elem = v[iter]
|
||||||
idxstr = join(coord, "_")
|
idxstr = join(coord, "_")
|
||||||
_hdf5plot_gwrite(vgrp, "v$idxstr", v[iter])
|
_hdf5plot_gwrite(vgrp, "v$idxstr", elem)
|
||||||
end
|
end
|
||||||
|
|
||||||
_hdf5plot_gwrite(vgrp, "dim", [sz...])
|
_hdf5plot_gwrite(vgrp, "dim", [sz...])
|
||||||
@ -402,10 +370,6 @@ end
|
|||||||
# return
|
# return
|
||||||
# end
|
# end
|
||||||
|
|
||||||
function _hdf5plot_gwrite(grp, k::String, v::SeriesAnnotations)
|
|
||||||
#Currently no support for SeriesAnnotations
|
|
||||||
return
|
|
||||||
end
|
|
||||||
function _hdf5plot_gwrite(grp, k::String, v::Subplot)
|
function _hdf5plot_gwrite(grp, k::String, v::Subplot)
|
||||||
grp = HDF5.g_create(grp, k)
|
grp = HDF5.g_create(grp, k)
|
||||||
_hdf5plot_gwrite(grp, "index", v[:subplot_index])
|
_hdf5plot_gwrite(grp, "index", v[:subplot_index])
|
||||||
@ -528,6 +492,29 @@ function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid)
|
|||||||
v = _hdf5plot_read(grp, k, Array, dtid)
|
v = _hdf5plot_read(grp, k, Array, dtid)
|
||||||
return tuple(v...)
|
return tuple(v...)
|
||||||
end
|
end
|
||||||
|
function _hdf5plot_read(grp, k::String, T::Type{PlotText}, dtid)
|
||||||
|
grp = HDF5.g_open(grp, k)
|
||||||
|
|
||||||
|
str = _hdf5plot_read(grp, "str")
|
||||||
|
font = _hdf5plot_read(grp, "font")
|
||||||
|
return PlotText(str, font)
|
||||||
|
end
|
||||||
|
function _hdf5plot_read(grp, k::String, T::Type{SeriesAnnotations}, dtid)
|
||||||
|
grp = HDF5.g_open(grp, k)
|
||||||
|
|
||||||
|
strs = _hdf5plot_read(grp, "strs")
|
||||||
|
font = _hdf5plot_read(grp, "font")
|
||||||
|
baseshape = _hdf5plot_read(grp, "baseshape")
|
||||||
|
scalefactor = _hdf5plot_read(grp, "scalefactor")
|
||||||
|
return SeriesAnnotations(strs, font, baseshape, scalefactor)
|
||||||
|
end
|
||||||
|
function _hdf5plot_read(grp, k::String, T::Type{Shape}, dtid)
|
||||||
|
grp = HDF5.g_open(grp, k)
|
||||||
|
|
||||||
|
x = _hdf5plot_read(grp, "x")
|
||||||
|
y = _hdf5plot_read(grp, "y")
|
||||||
|
return Shape(x, y)
|
||||||
|
end
|
||||||
function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid)
|
function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid)
|
||||||
grp = HDF5.g_open(grp, k)
|
grp = HDF5.g_open(grp, k)
|
||||||
|
|
||||||
@ -601,11 +588,6 @@ end
|
|||||||
function _hdf5plot_read(sp::Subplot, subpath::String, f)
|
function _hdf5plot_read(sp::Subplot, subpath::String, f)
|
||||||
f = f::HDF5.HDF5File #Assert
|
f = f::HDF5.HDF5File #Assert
|
||||||
|
|
||||||
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr"))
|
|
||||||
kwlist = KW()
|
|
||||||
_hdf5plot_read(grp, kwlist)
|
|
||||||
_hdf5_merge!(sp.attr, kwlist)
|
|
||||||
|
|
||||||
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list"))
|
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list"))
|
||||||
nseries = _hdf5plot_readcount(grp)
|
nseries = _hdf5plot_readcount(grp)
|
||||||
|
|
||||||
@ -617,6 +599,12 @@ function _hdf5plot_read(sp::Subplot, subpath::String, f)
|
|||||||
_hdf5_merge!(sp.series_list[end].plotattributes, kwlist)
|
_hdf5_merge!(sp.series_list[end].plotattributes, kwlist)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#Perform after adding series... otherwise values get overwritten:
|
||||||
|
grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr"))
|
||||||
|
kwlist = KW()
|
||||||
|
_hdf5plot_read(grp, kwlist)
|
||||||
|
_hdf5_merge!(sp.attr, kwlist)
|
||||||
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -14,61 +14,6 @@ Add in functionality to Plots.jl:
|
|||||||
=#
|
=#
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
#TODO: remove features
|
|
||||||
const _inspectdr_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
|
||||||
# :foreground_color_grid,
|
|
||||||
:foreground_color_legend, :foreground_color_title,
|
|
||||||
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
|
||||||
:label,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
|
||||||
:markerstrokestyle, #Causes warning not to have it... what is this?
|
|
||||||
:fillcolor, :fillalpha, #:fillrange,
|
|
||||||
# :bins, :bar_width, :bar_edges, :bar_position,
|
|
||||||
:title, :title_location,
|
|
||||||
:window_title,
|
|
||||||
:guide, :lims, :scale, #:ticks, :flip, :rotation,
|
|
||||||
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
|
||||||
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
|
||||||
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
|
||||||
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
|
||||||
:grid, #:gridalpha, :gridstyle, :gridlinewidth, #alhpa & linewidth are per plot - not per subplot
|
|
||||||
:legend, #:legendtitle, :colorbar,
|
|
||||||
# :marker_z,
|
|
||||||
# :line_z,
|
|
||||||
# :levels,
|
|
||||||
# :ribbon, :quiver, :arrow,
|
|
||||||
# :orientation,
|
|
||||||
:overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
# :normalize, :weights,
|
|
||||||
# :contours, :aspect_ratio,
|
|
||||||
:match_dimensions,
|
|
||||||
# :clims,
|
|
||||||
# :inset_subplots,
|
|
||||||
:dpi,
|
|
||||||
# :colorbar_title,
|
|
||||||
])
|
|
||||||
const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot]
|
|
||||||
const _inspectdr_seriestype = [
|
|
||||||
:path, :scatter, :shape, :straightline, #, :steppre, :steppost
|
|
||||||
]
|
|
||||||
#see: _allMarkers, _shape_keys
|
|
||||||
const _inspectdr_marker = Symbol[
|
|
||||||
:none, :auto,
|
|
||||||
:circle, :rect, :diamond,
|
|
||||||
:cross, :xcross,
|
|
||||||
:utriangle, :dtriangle, :rtriangle, :ltriangle,
|
|
||||||
:pentagon, :hexagon, :heptagon, :octagon,
|
|
||||||
:star4, :star5, :star6, :star7, :star8,
|
|
||||||
:vline, :hline, :+, :x,
|
|
||||||
]
|
|
||||||
|
|
||||||
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
|
|
||||||
|
|
||||||
is_marker_supported(::InspectDRBackend, shape::Shape) = true
|
is_marker_supported(::InspectDRBackend, shape::Shape) = true
|
||||||
|
|
||||||
|
|||||||
@ -2,47 +2,6 @@
|
|||||||
|
|
||||||
# significant contributions by: @pkofod
|
# significant contributions by: @pkofod
|
||||||
|
|
||||||
const _pgfplots_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend,
|
|
||||||
:background_color_inside,
|
|
||||||
# :background_color_outside,
|
|
||||||
# :foreground_color_legend,
|
|
||||||
:foreground_color_grid, :foreground_color_axis,
|
|
||||||
:foreground_color_text, :foreground_color_border,
|
|
||||||
:label,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins,
|
|
||||||
# :bar_width, :bar_edges,
|
|
||||||
:title,
|
|
||||||
# :window_title,
|
|
||||||
:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation,
|
|
||||||
:tickfont, :guidefont, :legendfont,
|
|
||||||
:grid, :legend,
|
|
||||||
:colorbar, :colorbar_title,
|
|
||||||
:fill_z, :line_z, :marker_z, :levels,
|
|
||||||
# :ribbon, :quiver, :arrow,
|
|
||||||
# :orientation,
|
|
||||||
# :overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
# :normalize, :weights, :contours,
|
|
||||||
:aspect_ratio,
|
|
||||||
# :match_dimensions,
|
|
||||||
:tick_direction,
|
|
||||||
:framestyle,
|
|
||||||
:camera,
|
|
||||||
:contour_labels,
|
|
||||||
])
|
|
||||||
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
|
|
||||||
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
|
||||||
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
|
|
||||||
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const _pgfplots_linestyles = KW(
|
const _pgfplots_linestyles = KW(
|
||||||
@ -446,7 +405,7 @@ function pgf_axis(sp::Subplot, letter)
|
|||||||
if framestyle == :zerolines
|
if framestyle == :zerolines
|
||||||
push!(style, string("extra ", letter, " ticks = 0"))
|
push!(style, string("extra ", letter, " ticks = 0"))
|
||||||
push!(style, string("extra ", letter, " tick labels = "))
|
push!(style, string("extra ", letter, " tick labels = "))
|
||||||
push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}}"))
|
push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
if !axis[:showaxis]
|
if !axis[:showaxis]
|
||||||
@ -455,7 +414,7 @@ function pgf_axis(sp::Subplot, letter)
|
|||||||
if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
|
if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
|
||||||
push!(style, string(letter, " axis line style = {draw opacity = 0}"))
|
push!(style, string(letter, " axis line style = {draw opacity = 0}"))
|
||||||
else
|
else
|
||||||
push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_axis], 1.0), "}"))
|
push!(style, string(letter, " axis line style = {", pgf_linestyle(pgf_thickness_scaling(sp), axis[:foreground_color_border], 1.0), "}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# return the style list and KW args
|
# return the style list and KW args
|
||||||
|
|||||||
@ -1,60 +1,6 @@
|
|||||||
|
|
||||||
# https://plot.ly/javascript/getting-started
|
# https://plot.ly/javascript/getting-started
|
||||||
|
|
||||||
const _plotly_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
|
||||||
:foreground_color_legend, :foreground_color_guide,
|
|
||||||
:foreground_color_grid, :foreground_color_axis,
|
|
||||||
:foreground_color_text, :foreground_color_border,
|
|
||||||
:foreground_color_title,
|
|
||||||
:label,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins,
|
|
||||||
:title, :title_location,
|
|
||||||
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
|
||||||
:titlefontcolor,
|
|
||||||
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
|
||||||
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
|
||||||
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
|
||||||
:window_title,
|
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
|
||||||
:tickfont, :guidefont, :legendfont,
|
|
||||||
:grid, :gridalpha, :gridlinewidth,
|
|
||||||
:legend, :colorbar, :colorbar_title,
|
|
||||||
:marker_z, :fill_z, :line_z, :levels,
|
|
||||||
:ribbon, :quiver,
|
|
||||||
:orientation,
|
|
||||||
# :overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
:normalize, :weights,
|
|
||||||
# :contours,
|
|
||||||
:aspect_ratio,
|
|
||||||
:hover,
|
|
||||||
:inset_subplots,
|
|
||||||
:bar_width,
|
|
||||||
:clims,
|
|
||||||
:framestyle,
|
|
||||||
:tick_direction,
|
|
||||||
:camera,
|
|
||||||
:contour_labels,
|
|
||||||
])
|
|
||||||
|
|
||||||
const _plotly_seriestype = [
|
|
||||||
:path, :scatter, :pie, :heatmap,
|
|
||||||
:contour, :surface, :wireframe, :path3d, :scatter3d, :shape, :scattergl,
|
|
||||||
:straightline
|
|
||||||
]
|
|
||||||
const _plotly_style = [:auto, :solid, :dash, :dot, :dashdot]
|
|
||||||
const _plotly_marker = [
|
|
||||||
:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle,
|
|
||||||
:cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline
|
|
||||||
]
|
|
||||||
const _plotly_scale = [:identity, :log10]
|
|
||||||
is_subplot_supported(::PlotlyBackend) = true
|
is_subplot_supported(::PlotlyBackend) = true
|
||||||
# is_string_supported(::PlotlyBackend) = true
|
# is_string_supported(::PlotlyBackend) = true
|
||||||
const _plotly_framestyles = [:box, :axes, :zerolines, :grid, :none]
|
const _plotly_framestyles = [:box, :axes, :zerolines, :grid, :none]
|
||||||
@ -71,30 +17,9 @@ end
|
|||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
const plotly_remote_file_path = "https://cdn.plot.ly/plotly-latest.min.js"
|
||||||
|
|
||||||
|
|
||||||
const _plotly_js_path = joinpath(dirname(@__FILE__), "..", "..", "deps", "plotly-latest.min.js")
|
|
||||||
const _plotly_js_path_remote = "https://cdn.plot.ly/plotly-latest.min.js"
|
|
||||||
|
|
||||||
_js_code = open(read, _plotly_js_path, "r")
|
|
||||||
|
|
||||||
# borrowed from https://github.com/plotly/plotly.py/blob/2594076e29584ede2d09f2aa40a8a195b3f3fc66/plotly/offline/offline.py#L64-L71 c/o @spencerlyon2
|
|
||||||
_js_script = """
|
|
||||||
<script type='text/javascript'>
|
|
||||||
define('plotly', function(require, exports, module) {
|
|
||||||
$(_js_code)
|
|
||||||
});
|
|
||||||
require(['plotly'], function(Plotly) {
|
|
||||||
window.Plotly = Plotly;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
"""
|
|
||||||
|
|
||||||
# if we're in IJulia call setupnotebook to load js and css
|
|
||||||
if isijulia()
|
|
||||||
display("text/html", _js_script)
|
|
||||||
end
|
|
||||||
|
|
||||||
# if isatom()
|
# if isatom()
|
||||||
# import Atom
|
# import Atom
|
||||||
# Atom.@msg evaljs(_js_code)
|
# Atom.@msg evaljs(_js_code)
|
||||||
@ -102,8 +27,6 @@ end
|
|||||||
using UUIDs
|
using UUIDs
|
||||||
|
|
||||||
push!(_initialized_backends, :plotly)
|
push!(_initialized_backends, :plotly)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
const _plotly_legend_pos = KW(
|
const _plotly_legend_pos = KW(
|
||||||
@ -115,7 +38,7 @@ const _plotly_legend_pos = KW(
|
|||||||
:bottomright => [1., 0.],
|
:bottomright => [1., 0.],
|
||||||
:topright => [1., 1.],
|
:topright => [1., 1.],
|
||||||
:topleft => [0., 1.]
|
:topleft => [0., 1.]
|
||||||
)
|
)
|
||||||
|
|
||||||
plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.])
|
plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.])
|
||||||
plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v
|
plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v
|
||||||
@ -882,12 +805,27 @@ plotly_series_json(plt::Plot) = JSON.json(plotly_series(plt))
|
|||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
const _use_remote = Ref(false)
|
const ijulia_initialized = Ref(false)
|
||||||
|
|
||||||
function html_head(plt::Plot{PlotlyBackend})
|
function html_head(plt::Plot{PlotlyBackend})
|
||||||
jsfilename = _use_remote[] ? _plotly_js_path_remote : ("file://" * _plotly_js_path)
|
local_file = ("file://" * plotly_local_file_path)
|
||||||
# "<script src=\"$(joinpath(dirname(@__FILE__),"..","..","deps","plotly-latest.min.js"))\"></script>"
|
plotly = use_local_dependencies[] ? local_file : plotly_remote_file_path
|
||||||
"<script src=\"$jsfilename\"></script>"
|
if isijulia() && !ijulia_initialized[]
|
||||||
|
# using requirejs seems to be key to load a js depency in IJulia!
|
||||||
|
# https://requirejs.org/docs/start.html
|
||||||
|
# https://github.com/JuliaLang/IJulia.jl/issues/345
|
||||||
|
display("text/html", """
|
||||||
|
<script type="text/javascript">
|
||||||
|
requirejs([$(repr(plotly))], function(p) {
|
||||||
|
window.Plotly = p
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
""")
|
||||||
|
ijulia_initialized[] = true
|
||||||
|
end
|
||||||
|
# IJulia just needs one initialization
|
||||||
|
isijulia() && return ""
|
||||||
|
return "<script src=$(repr(plotly))></script>"
|
||||||
end
|
end
|
||||||
|
|
||||||
function html_body(plt::Plot{PlotlyBackend}, style = nothing)
|
function html_body(plt::Plot{PlotlyBackend}, style = nothing)
|
||||||
@ -908,8 +846,8 @@ end
|
|||||||
|
|
||||||
function js_body(plt::Plot{PlotlyBackend}, uuid)
|
function js_body(plt::Plot{PlotlyBackend}, uuid)
|
||||||
js = """
|
js = """
|
||||||
PLOT = document.getElementById('$(uuid)');
|
PLOT = document.getElementById('$(uuid)');
|
||||||
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
|
Plotly.plot(PLOT, $(plotly_series_json(plt)), $(plotly_layout_json(plt)));
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,12 @@
|
|||||||
|
|
||||||
# https://github.com/spencerlyon2/PlotlyJS.jl
|
# https://github.com/spencerlyon2/PlotlyJS.jl
|
||||||
|
|
||||||
const _plotlyjs_attr = _plotly_attr
|
|
||||||
const _plotlyjs_seriestype = _plotly_seriestype
|
|
||||||
const _plotlyjs_style = _plotly_style
|
|
||||||
const _plotlyjs_marker = _plotly_marker
|
|
||||||
const _plotlyjs_scale = _plotly_scale
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
|
function _create_backend_figure(plt::Plot{PlotlyJSBackend})
|
||||||
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
|
if !isplotnull() && plt[:overwrite_figure] && isa(current().o, PlotlyJS.SyncPlot)
|
||||||
p = PlotlyJS.plot()
|
PlotlyJS.SyncPlot(PlotlyJS.Plot(), options = current().o.options)
|
||||||
p.window = current().o.window
|
|
||||||
p
|
|
||||||
else
|
else
|
||||||
PlotlyJS.plot()
|
PlotlyJS.plot()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,55 +1,9 @@
|
|||||||
|
# Do "using PyPlot: PyCall, LaTeXStrings" without dependency warning:
|
||||||
|
const PyCall = PyPlot.PyCall
|
||||||
|
const LaTeXStrings = PyPlot.LaTeXStrings
|
||||||
|
|
||||||
# https://github.com/stevengj/PyPlot.jl
|
# https://github.com/stevengj/PyPlot.jl
|
||||||
|
|
||||||
const _pyplot_attr = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
|
||||||
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
|
|
||||||
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
|
|
||||||
:label,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins, :bar_width, :bar_edges, :bar_position,
|
|
||||||
:title, :title_location, :titlefont,
|
|
||||||
:window_title,
|
|
||||||
:guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation,
|
|
||||||
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
|
||||||
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
|
||||||
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
|
||||||
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
|
||||||
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
|
||||||
:legend, :legendtitle, :colorbar,
|
|
||||||
:marker_z, :line_z, :fill_z,
|
|
||||||
:levels,
|
|
||||||
:ribbon, :quiver, :arrow,
|
|
||||||
:orientation,
|
|
||||||
:overwrite_figure,
|
|
||||||
:polar,
|
|
||||||
:normalize, :weights,
|
|
||||||
:contours, :aspect_ratio,
|
|
||||||
:match_dimensions,
|
|
||||||
:clims,
|
|
||||||
:inset_subplots,
|
|
||||||
:dpi,
|
|
||||||
:colorbar_title,
|
|
||||||
:stride,
|
|
||||||
:framestyle,
|
|
||||||
:tick_direction,
|
|
||||||
:camera,
|
|
||||||
:contour_labels,
|
|
||||||
])
|
|
||||||
const _pyplot_seriestype = [
|
|
||||||
:path, :steppre, :steppost, :shape, :straightline,
|
|
||||||
:scatter, :hexbin, #:histogram2d, :histogram,
|
|
||||||
# :bar,
|
|
||||||
:heatmap, :pie, :image,
|
|
||||||
:contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe
|
|
||||||
]
|
|
||||||
const _pyplot_style = [:auto, :solid, :dash, :dot, :dashdot]
|
|
||||||
const _pyplot_marker = vcat(_allMarkers, :pixel)
|
|
||||||
const _pyplot_scale = [:identity, :ln, :log2, :log10]
|
|
||||||
is_marker_supported(::PyPlotBackend, shape::Shape) = true
|
is_marker_supported(::PyPlotBackend, shape::Shape) = true
|
||||||
|
|
||||||
|
|
||||||
@ -236,26 +190,22 @@ function add_pyfixedformatter(cbar, vals::AVec)
|
|||||||
cbar[:update_ticks]()
|
cbar[:update_ticks]()
|
||||||
end
|
end
|
||||||
|
|
||||||
@require LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" begin
|
function labelfunc(scale::Symbol, backend::PyPlotBackend)
|
||||||
function labelfunc(scale::Symbol, backend::PyPlotBackend)
|
if scale == :log10
|
||||||
if scale == :log10
|
x -> LaTeXStrings.latexstring("10^{$x}")
|
||||||
x -> LaTeXStrings.latexstring("10^{$x}")
|
elseif scale == :log2
|
||||||
elseif scale == :log2
|
x -> LaTeXStrings.latexstring("2^{$x}")
|
||||||
x -> LaTeXStrings.latexstring("2^{$x}")
|
elseif scale == :ln
|
||||||
elseif scale == :ln
|
x -> LaTeXStrings.latexstring("e^{$x}")
|
||||||
x -> LaTeXStrings.latexstring("e^{$x}")
|
else
|
||||||
else
|
string
|
||||||
string
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@require PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" begin
|
function py_mask_nans(z)
|
||||||
function py_mask_nans(z)
|
# pynp["ma"][:masked_invalid](z)))
|
||||||
# pynp["ma"][:masked_invalid](z)))
|
PyCall.pycall(pynp["ma"][:masked_invalid], Any, z)
|
||||||
PyCall.pycall(pynp["ma"][:masked_invalid], Any, z)
|
# pynp["ma"][:masked_where](pynp["isnan"](z),z)
|
||||||
# pynp["ma"][:masked_where](pynp["isnan"](z),z)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@ -272,17 +222,6 @@ function fix_xy_lengths!(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# total hack due to PyPlot bug (see issue #145).
|
|
||||||
# hack: duplicate the color vector when the total rgba fields is the same as the series length
|
|
||||||
function py_color_fix(c, x)
|
|
||||||
if (typeof(c) <: AbstractArray && length(c)*4 == length(x)) ||
|
|
||||||
(typeof(c) <: Tuple && length(x) == 4)
|
|
||||||
vcat(c, c)
|
|
||||||
else
|
|
||||||
c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
py_linecolor(series::Series) = py_color(series[:linecolor])
|
py_linecolor(series::Series) = py_color(series[:linecolor])
|
||||||
py_markercolor(series::Series) = py_color(series[:markercolor])
|
py_markercolor(series::Series) = py_color(series[:markercolor])
|
||||||
py_markerstrokecolor(series::Series) = py_color(series[:markerstrokecolor])
|
py_markerstrokecolor(series::Series) = py_color(series[:markerstrokecolor])
|
||||||
@ -439,7 +378,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
vmin, vmax = clims = get_clims(sp)
|
vmin, vmax = clims = get_clims(sp)
|
||||||
|
|
||||||
# Dict to store extra kwargs
|
# Dict to store extra kwargs
|
||||||
extrakw = KW(:vmin => vmin, :vmax => vmax)
|
if st == :wireframe
|
||||||
|
extrakw = KW() # vmin, vmax cause an error for wireframe plot
|
||||||
|
else
|
||||||
|
extrakw = KW(:vmin => vmin, :vmax => vmax)
|
||||||
|
end
|
||||||
|
|
||||||
# holds references to any python object representing the matplotlib series
|
# holds references to any python object representing the matplotlib series
|
||||||
handles = []
|
handles = []
|
||||||
@ -547,7 +490,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
else
|
else
|
||||||
py_color(plot_color(series[:markercolor], series[:markeralpha]))
|
py_color(plot_color(series[:markercolor], series[:markeralpha]))
|
||||||
end
|
end
|
||||||
extrakw[:c] = py_color_fix(markercolor, x)
|
extrakw[:c] = if markercolor isa Array
|
||||||
|
permutedims(hcat([[m...] for m in markercolor]...),[2,1])
|
||||||
|
elseif markercolor isa Tuple
|
||||||
|
reshape([markercolor...], 1, length(markercolor))
|
||||||
|
else
|
||||||
|
error("This case is not handled. Please file an issue.")
|
||||||
|
end
|
||||||
xyargs = if st == :bar && !isvertical(series)
|
xyargs = if st == :bar && !isvertical(series)
|
||||||
(y, x)
|
(y, x)
|
||||||
else
|
else
|
||||||
@ -555,7 +504,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if isa(series[:markershape], AbstractVector{Shape})
|
if isa(series[:markershape], AbstractVector{Shape})
|
||||||
# this section will create one scatter per data point to accomodate the
|
# this section will create one scatter per data point to accommodate the
|
||||||
# vector of shapes
|
# vector of shapes
|
||||||
handle = []
|
handle = []
|
||||||
x,y = xyargs
|
x,y = xyargs
|
||||||
@ -839,7 +788,7 @@ function py_set_ticks(ax, ticks, letter)
|
|||||||
if ticks == :none || ticks == nothing || ticks == false
|
if ticks == :none || ticks == nothing || ticks == false
|
||||||
kw = KW()
|
kw = KW()
|
||||||
for dir in (:top,:bottom,:left,:right)
|
for dir in (:top,:bottom,:left,:right)
|
||||||
kw[dir] = kw[Symbol(:label,dir)] = "off"
|
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||||
end
|
end
|
||||||
axis[:set_tick_params](;which="both", kw...)
|
axis[:set_tick_params](;which="both", kw...)
|
||||||
return
|
return
|
||||||
@ -1064,7 +1013,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
|
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
|
||||||
# don't show the 0 tick label for the origin framestyle
|
# don't show the 0 tick label for the origin framestyle
|
||||||
if sp[:framestyle] == :origin && length(ticks) > 1
|
if sp[:framestyle] == :origin && length(ticks) > 1
|
||||||
ticks[2][ticks[1] .== 0] = ""
|
ticks[2][ticks[1] .== 0] .= ""
|
||||||
end
|
end
|
||||||
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
|
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
|
||||||
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
|
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
|
||||||
@ -1102,7 +1051,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
else
|
else
|
||||||
ax[:spines][string(dir)][:set_visible](false)
|
ax[:spines][string(dir)][:set_visible](false)
|
||||||
end
|
end
|
||||||
kw[dir] = kw[Symbol(:label,dir)] = "off"
|
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||||
end
|
end
|
||||||
ax[:xaxis][:set_tick_params](; which="both", kw...)
|
ax[:xaxis][:set_tick_params](; which="both", kw...)
|
||||||
end
|
end
|
||||||
@ -1112,7 +1061,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
if !ispolar(sp)
|
if !ispolar(sp)
|
||||||
ax[:spines][string(dir)][:set_visible](false)
|
ax[:spines][string(dir)][:set_visible](false)
|
||||||
end
|
end
|
||||||
kw[dir] = kw[Symbol(:label,dir)] = "off"
|
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||||
end
|
end
|
||||||
ax[:yaxis][:set_tick_params](; which="both", kw...)
|
ax[:yaxis][:set_tick_params](; which="both", kw...)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,28 +1,6 @@
|
|||||||
|
|
||||||
# https://github.com/Evizero/UnicodePlots.jl
|
# https://github.com/Evizero/UnicodePlots.jl
|
||||||
|
|
||||||
const _unicodeplots_attr = merge_with_base_supported([
|
|
||||||
:label,
|
|
||||||
:legend,
|
|
||||||
:seriescolor,
|
|
||||||
:seriesalpha,
|
|
||||||
:linestyle,
|
|
||||||
:markershape,
|
|
||||||
:bins,
|
|
||||||
:title,
|
|
||||||
:guide, :lims,
|
|
||||||
])
|
|
||||||
const _unicodeplots_seriestype = [
|
|
||||||
:path, :scatter, :straightline,
|
|
||||||
# :bar,
|
|
||||||
:shape,
|
|
||||||
:histogram2d,
|
|
||||||
:spy
|
|
||||||
]
|
|
||||||
const _unicodeplots_style = [:auto, :solid]
|
|
||||||
const _unicodeplots_marker = [:none, :auto, :circle]
|
|
||||||
const _unicodeplots_scale = [:identity]
|
|
||||||
|
|
||||||
|
|
||||||
# don't warn on unsupported... there's just too many warnings!!
|
# don't warn on unsupported... there's just too many warnings!!
|
||||||
warnOnUnsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
|
warnOnUnsupported_args(::UnicodePlotsBackend, plotattributes::KW) = nothing
|
||||||
|
|||||||
@ -42,8 +42,14 @@ function write_temp_html(plt::AbstractPlot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function standalone_html_window(plt::AbstractPlot)
|
function standalone_html_window(plt::AbstractPlot)
|
||||||
|
old = use_local_dependencies[] # save state to restore afterwards
|
||||||
|
# if we open a browser ourself, we can host local files, so
|
||||||
|
# when we have a local plotly downloaded this is the way to go!
|
||||||
|
use_local_dependencies[] = isfile(plotly_local_file_path)
|
||||||
filename = write_temp_html(plt)
|
filename = write_temp_html(plt)
|
||||||
open_browser_window(filename)
|
open_browser_window(filename)
|
||||||
|
# restore for other backends
|
||||||
|
use_local_dependencies[] = old
|
||||||
end
|
end
|
||||||
|
|
||||||
# uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html
|
# uses wkhtmltopdf/wkhtmltoimage: http://wkhtmltopdf.org/downloads.html
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
const P2 = FixedSizeArrays.Vec{2,Float64}
|
const P2 = StaticArrays.SVector{2,Float64}
|
||||||
const P3 = FixedSizeArrays.Vec{3,Float64}
|
const P3 = StaticArrays.SVector{3,Float64}
|
||||||
|
|
||||||
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
|
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
|
||||||
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
|
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
|
||||||
@ -491,7 +491,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
|
|||||||
# with a list of custom shapes for each
|
# with a list of custom shapes for each
|
||||||
msw,msh = anns.scalefactor
|
msw,msh = anns.scalefactor
|
||||||
msize = Float64[]
|
msize = Float64[]
|
||||||
shapes = Vector{Shape}(length(anns.strs))
|
shapes = Vector{Shape}(undef, length(anns.strs))
|
||||||
for i in eachindex(anns.strs)
|
for i in eachindex(anns.strs)
|
||||||
str = _cycle(anns.strs,i)
|
str = _cycle(anns.strs,i)
|
||||||
|
|
||||||
@ -509,7 +509,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
|
|||||||
# and then re-scale a copy of baseshape to match the w/h ratio
|
# and then re-scale a copy of baseshape to match the w/h ratio
|
||||||
maxscale = max(xscale, yscale)
|
maxscale = max(xscale, yscale)
|
||||||
push!(msize, maxscale)
|
push!(msize, maxscale)
|
||||||
baseshape = _cycle(get(anns.baseshape),i)
|
baseshape = _cycle(anns.baseshape, i)
|
||||||
shapes[i] = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
|
shapes[i] = scale(baseshape, msw*xscale/maxscale, msh*yscale/maxscale, (0,0))
|
||||||
end
|
end
|
||||||
series[:markershape] = shapes
|
series[:markershape] = shapes
|
||||||
@ -736,7 +736,7 @@ end
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
"create a BezierCurve for plotting"
|
"create a BezierCurve for plotting"
|
||||||
mutable struct BezierCurve{T <: FixedSizeArrays.Vec}
|
mutable struct BezierCurve{T <: StaticArrays.SVector}
|
||||||
control_points::Vector{T}
|
control_points::Vector{T}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -750,7 +750,7 @@ function (bc::BezierCurve)(t::Real)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
|
# mean(x::Real, y::Real) = 0.5*(x+y) #commented out as I cannot see this used anywhere and it overwrites a Base method with different functionality
|
||||||
# mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
|
# mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps) # I also could not see this used anywhere, and it's type piracy - implementing a NaNMath version for this would just involve converting to a standard array
|
||||||
|
|
||||||
@deprecate curve_points coords
|
@deprecate curve_points coords
|
||||||
|
|
||||||
|
|||||||
@ -1,208 +0,0 @@
|
|||||||
|
|
||||||
# https://github.com/bokeh/Bokeh.jl
|
|
||||||
|
|
||||||
|
|
||||||
supported_attrs(::BokehBackend) = merge_with_base_supported([
|
|
||||||
# :annotations,
|
|
||||||
# :axis,
|
|
||||||
# :background_color,
|
|
||||||
:linecolor,
|
|
||||||
# :color_palette,
|
|
||||||
# :fillrange,
|
|
||||||
# :fillcolor,
|
|
||||||
# :fillalpha,
|
|
||||||
# :foreground_color,
|
|
||||||
:group,
|
|
||||||
# :label,
|
|
||||||
# :layout,
|
|
||||||
# :legend,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linestyle,
|
|
||||||
:seriestype,
|
|
||||||
:linewidth,
|
|
||||||
# :linealpha,
|
|
||||||
:markershape,
|
|
||||||
:markercolor,
|
|
||||||
:markersize,
|
|
||||||
# :markeralpha,
|
|
||||||
# :markerstrokewidth,
|
|
||||||
# :markerstrokecolor,
|
|
||||||
# :markerstrokestyle,
|
|
||||||
# :n,
|
|
||||||
# :bins,
|
|
||||||
# :nc,
|
|
||||||
# :nr,
|
|
||||||
# :pos,
|
|
||||||
# :smooth,
|
|
||||||
# :show,
|
|
||||||
:size,
|
|
||||||
:title,
|
|
||||||
# :window_title,
|
|
||||||
:x,
|
|
||||||
# :xguide,
|
|
||||||
# :xlims,
|
|
||||||
# :xticks,
|
|
||||||
:y,
|
|
||||||
# :yguide,
|
|
||||||
# :ylims,
|
|
||||||
# :yrightlabel,
|
|
||||||
# :yticks,
|
|
||||||
# :xscale,
|
|
||||||
# :yscale,
|
|
||||||
# :xflip,
|
|
||||||
# :yflip,
|
|
||||||
# :z,
|
|
||||||
# :tickfont,
|
|
||||||
# :guidefont,
|
|
||||||
# :legendfont,
|
|
||||||
# :grid,
|
|
||||||
# :surface,
|
|
||||||
# :levels,
|
|
||||||
])
|
|
||||||
supported_types(::BokehBackend) = [:path, :scatter]
|
|
||||||
supported_styles(::BokehBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
|
||||||
supported_markers(::BokehBackend) = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5]
|
|
||||||
supported_scales(::BokehBackend) = [:identity, :ln]
|
|
||||||
is_subplot_supported(::BokehBackend) = false
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _initialize_backend(::BokehBackend; kw...)
|
|
||||||
@eval begin
|
|
||||||
@warn("Bokeh is no longer supported... many features will likely be broken.")
|
|
||||||
import Bokeh
|
|
||||||
export Bokeh
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
const _glyphtypes = KW(
|
|
||||||
:circle => :Circle,
|
|
||||||
:rect => :Square,
|
|
||||||
:diamond => :Diamond,
|
|
||||||
:utriangle => :Triangle,
|
|
||||||
:dtriangle => :InvertedTriangle,
|
|
||||||
# :pentagon =>
|
|
||||||
# :hexagon =>
|
|
||||||
# :heptagon =>
|
|
||||||
# :octagon =>
|
|
||||||
:cross => :Cross,
|
|
||||||
:xcross => :X,
|
|
||||||
:star5 => :Asterisk,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
function bokeh_glyph_type(plotattributes::KW)
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
mt = plotattributes[:markershape]
|
|
||||||
if st == :scatter && mt == :none
|
|
||||||
mt = :circle
|
|
||||||
end
|
|
||||||
|
|
||||||
# if we have a marker, use that
|
|
||||||
if st == :scatter || mt != :none
|
|
||||||
return _glyphtypes[mt]
|
|
||||||
end
|
|
||||||
|
|
||||||
# otherwise return a line
|
|
||||||
return :Line
|
|
||||||
end
|
|
||||||
|
|
||||||
function get_stroke_vector(linestyle::Symbol)
|
|
||||||
dash = 12
|
|
||||||
dot = 3
|
|
||||||
gap = 2
|
|
||||||
linestyle == :solid && return Int[]
|
|
||||||
linestyle == :dash && return Int[dash, gap]
|
|
||||||
linestyle == :dot && return Int[dot, gap]
|
|
||||||
linestyle == :dashdot && return Int[dash, gap, dot, gap]
|
|
||||||
linestyle == :dashdotdot && return Int[dash, gap, dot, gap, dot, gap]
|
|
||||||
error("unsupported linestyle: ", linestyle)
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# function _create_plot(pkg::BokehBackend, plotattributes::KW)
|
|
||||||
function _create_backend_figure(plt::Plot{BokehBackend})
|
|
||||||
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
|
|
||||||
# TODO: initialize the plot... title, xlabel, bgcolor, etc
|
|
||||||
|
|
||||||
datacolumns = Bokeh.BokehDataSet[]
|
|
||||||
tools = Bokeh.tools()
|
|
||||||
filename = tempname() * ".html"
|
|
||||||
title = plt.attr[:title]
|
|
||||||
w, h = plt.attr[:size]
|
|
||||||
xaxis_type = plt.attr[:xscale] == :log10 ? :log : :auto
|
|
||||||
yaxis_type = plt.attr[:yscale] == :log10 ? :log : :auto
|
|
||||||
# legend = plt.attr[:legend] ? xxxx : nothing
|
|
||||||
legend = nothing
|
|
||||||
extra_args = KW() # TODO: we'll put extra settings (xlim, etc) here
|
|
||||||
Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args)
|
|
||||||
|
|
||||||
# Plot(bplt, pkg, 0, plotattributes, KW[])
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# function _series_added(::BokehBackend, plt::Plot, plotattributes::KW)
|
|
||||||
function _series_added(plt::Plot{BokehBackend}, series::Series)
|
|
||||||
bdata = Dict{Symbol, Vector}(:x => collect(series.plotattributes[:x]), :y => collect(series.plotattributes[:y]))
|
|
||||||
|
|
||||||
glyph = Bokeh.Bokehjs.Glyph(
|
|
||||||
glyphtype = bokeh_glyph_type(plotattributes),
|
|
||||||
linecolor = webcolor(plotattributes[:linecolor]), # shape's stroke or line color
|
|
||||||
linewidth = plotattributes[:linewidth], # shape's stroke width or line width
|
|
||||||
fillcolor = webcolor(plotattributes[:markercolor]),
|
|
||||||
size = ceil(Int, plotattributes[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends
|
|
||||||
dash = get_stroke_vector(plotattributes[:linestyle])
|
|
||||||
)
|
|
||||||
|
|
||||||
legend = nothing # TODO
|
|
||||||
push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend))
|
|
||||||
|
|
||||||
# push!(plt.seriesargs, plotattributes)
|
|
||||||
# plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# TODO: override this to update plot items (title, xlabel, etc) after creation
|
|
||||||
function _update_plot_object(plt::Plot{BokehBackend}, plotattributes::KW)
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# accessors for x/y data
|
|
||||||
|
|
||||||
# function getxy(plt::Plot{BokehBackend}, i::Int)
|
|
||||||
# series = plt.o.datacolumns[i].data
|
|
||||||
# series[:x], series[:y]
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# function setxy!(plt::Plot{BokehBackend}, xy::Tuple{X,Y}, i::Integer)
|
|
||||||
# series = plt.o.datacolumns[i].data
|
|
||||||
# series[:x], series[:y] = xy
|
|
||||||
# plt
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{BokehBackend})
|
|
||||||
# TODO: write a png to io
|
|
||||||
@warn("mime png not implemented")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Base.display(::PlotsDisplay, plt::Plot{BokehBackend})
|
|
||||||
Bokeh.showplot(plt.o)
|
|
||||||
end
|
|
||||||
|
|
||||||
# function Base.display(::PlotsDisplay, plt::Subplot{BokehBackend})
|
|
||||||
# # TODO: display/show the subplot
|
|
||||||
# end
|
|
||||||
@ -1,744 +0,0 @@
|
|||||||
|
|
||||||
# https://github.com/dcjones/Gadfly.jl
|
|
||||||
|
|
||||||
|
|
||||||
supported_attrs(::GadflyBackend) = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:background_color, :foreground_color, :color_palette,
|
|
||||||
:group, :label, :seriestype,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linecolor, :linestyle, :linewidth, :linealpha,
|
|
||||||
:markershape, :markercolor, :markersize, :markeralpha,
|
|
||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
|
||||||
:bins, :n, :nc, :nr, :layout, :smooth,
|
|
||||||
:title, :window_title, :show, :size,
|
|
||||||
:x, :xguide, :xlims, :xticks, :xscale, :xflip,
|
|
||||||
:y, :yguide, :ylims, :yticks, :yscale, :yflip,
|
|
||||||
:z,
|
|
||||||
:tickfont, :guidefont, :legendfont,
|
|
||||||
:grid, :legend, :colorbar,
|
|
||||||
:marker_z, :levels,
|
|
||||||
:xerror, :yerror,
|
|
||||||
:ribbon, :quiver,
|
|
||||||
:orientation,
|
|
||||||
])
|
|
||||||
supported_types(::GadflyBackend) = [
|
|
||||||
:path,
|
|
||||||
:scatter, :hexbin,
|
|
||||||
:bar,
|
|
||||||
:contour, :shape
|
|
||||||
]
|
|
||||||
supported_styles(::GadflyBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
|
||||||
supported_markers(::GadflyBackend) = vcat(_allMarkers, Shape)
|
|
||||||
supported_scales(::GadflyBackend) = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
|
|
||||||
is_subplot_supported(::GadflyBackend) = true
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function _initialize_backend(::GadflyBackend; kw...)
|
|
||||||
@eval begin
|
|
||||||
import Gadfly, Compose
|
|
||||||
export Gadfly, Compose
|
|
||||||
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# immutable MissingVec <: AbstractVector{Float64} end
|
|
||||||
# Base.size(v::MissingVec) = (1,)
|
|
||||||
# Base.getindex(v::MissingVec, i::Integer) = 0.0
|
|
||||||
|
|
||||||
function createGadflyPlotObject(plotattributes::KW)
|
|
||||||
gplt = Gadfly.Plot()
|
|
||||||
gplt.mapping = Dict()
|
|
||||||
gplt.data_source = Gadfly.DataFrames.DataFrame()
|
|
||||||
# gplt.layers = gplt.layers[1:0]
|
|
||||||
gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());]
|
|
||||||
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(plotattributes[:xguide]),
|
|
||||||
Gadfly.Guide.ylabel(plotattributes[:yguide]),
|
|
||||||
Gadfly.Guide.title(plotattributes[:title])]
|
|
||||||
gplt
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function getLineGeom(plotattributes::KW)
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
xbins, ybins = maketuple(plotattributes[:bins])
|
|
||||||
if st == :hexb
|
|
||||||
Gadfly.Geom.hexbin(xbincount = xbins, ybincount = ybins)
|
|
||||||
elseif st == :histogram2d
|
|
||||||
Gadfly.Geom.histogram2d(xbincount = xbins, ybincount = ybins)
|
|
||||||
elseif st == :histogram
|
|
||||||
Gadfly.Geom.histogram(bincount = xbins,
|
|
||||||
orientation = isvertical(plotattributes) ? :vertical : :horizontal,
|
|
||||||
position = plotattributes[:bar_position] == :stack ? :stack : :dodge)
|
|
||||||
elseif st == :path
|
|
||||||
Gadfly.Geom.path
|
|
||||||
elseif st in (:bar, :sticks)
|
|
||||||
Gadfly.Geom.bar
|
|
||||||
elseif st == :steppost
|
|
||||||
Gadfly.Geom.step
|
|
||||||
elseif st == :steppre
|
|
||||||
Gadfly.Geom.step(direction = :vh)
|
|
||||||
elseif st == :hline
|
|
||||||
Gadfly.Geom.hline
|
|
||||||
elseif st == :vline
|
|
||||||
Gadfly.Geom.vline
|
|
||||||
elseif st == :contour
|
|
||||||
Gadfly.Geom.contour(levels = plotattributes[:levels])
|
|
||||||
# elseif st == :shape
|
|
||||||
# Gadfly.Geom.polygon(fill = true, preserve_order = true)
|
|
||||||
else
|
|
||||||
nothing
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function get_extra_theme_args(plotattributes::KW, k::Symbol)
|
|
||||||
# gracefully handles old Gadfly versions
|
|
||||||
extra_theme_args = KW()
|
|
||||||
try
|
|
||||||
extra_theme_args[:line_style] = Gadfly.get_stroke_vector(plotattributes[k])
|
|
||||||
catch err
|
|
||||||
if string(err) == "UndefVarError(:get_stroke_vector)"
|
|
||||||
Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?")
|
|
||||||
else
|
|
||||||
rethrow()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
extra_theme_args
|
|
||||||
end
|
|
||||||
|
|
||||||
function getGadflyLineTheme(plotattributes::KW)
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
lc = convertColor(getColor(plotattributes[:linecolor]), plotattributes[:linealpha])
|
|
||||||
fc = convertColor(getColor(plotattributes[:fillcolor]), plotattributes[:fillalpha])
|
|
||||||
|
|
||||||
Gadfly.Theme(;
|
|
||||||
default_color = (st in (:histogram,:histogram2d,:hexbin,:bar,:sticks) ? fc : lc),
|
|
||||||
line_width = (st == :sticks ? 1 : plotattributes[:linewidth]) * Gadfly.px,
|
|
||||||
# line_style = Gadfly.get_stroke_vector(plotattributes[:linestyle]),
|
|
||||||
lowlight_color = x->RGB(fc), # fill/ribbon
|
|
||||||
lowlight_opacity = alpha(fc), # fill/ribbon
|
|
||||||
bar_highlight = RGB(lc), # bars
|
|
||||||
get_extra_theme_args(plotattributes, :linestyle)...
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# add a line as a new layer
|
|
||||||
function addGadflyLine!(plt::Plot, numlayers::Int, plotattributes::KW, geoms...)
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
gfargs = vcat(geoms..., getGadflyLineTheme(plotattributes))
|
|
||||||
kwargs = KW()
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
|
|
||||||
# add a fill?
|
|
||||||
if plotattributes[:fillrange] != nothing && st != :contour
|
|
||||||
fillmin, fillmax = map(makevec, maketuple(plotattributes[:fillrange]))
|
|
||||||
nmin, nmax = length(fillmin), length(fillmax)
|
|
||||||
kwargs[:ymin] = Float64[min(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])]
|
|
||||||
kwargs[:ymax] = Float64[max(y, fillmin[mod1(i, nmin)], fillmax[mod1(i, nmax)]) for (i,y) in enumerate(plotattributes[:y])]
|
|
||||||
push!(gfargs, Gadfly.Geom.ribbon)
|
|
||||||
end
|
|
||||||
|
|
||||||
if st in (:hline, :vline)
|
|
||||||
kwargs[st == :hline ? :yintercept : :xintercept] = plotattributes[:y]
|
|
||||||
|
|
||||||
else
|
|
||||||
if st == :sticks
|
|
||||||
w = 0.01 * mean(diff(plotattributes[:x]))
|
|
||||||
kwargs[:xmin] = plotattributes[:x] - w
|
|
||||||
kwargs[:xmax] = plotattributes[:x] + w
|
|
||||||
elseif st == :contour
|
|
||||||
kwargs[:z] = plotattributes[:z].surf
|
|
||||||
addGadflyContColorScale(plt, plotattributes[:linecolor])
|
|
||||||
end
|
|
||||||
|
|
||||||
kwargs[:x] = plotattributes[st == :histogram ? :y : :x]
|
|
||||||
kwargs[:y] = plotattributes[:y]
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
# # add the layer
|
|
||||||
Gadfly.layer(gfargs...; order=numlayers, kwargs...)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
get_shape(sym::Symbol) = _shapes[sym]
|
|
||||||
get_shape(shape::Shape) = shape
|
|
||||||
|
|
||||||
# extract the underlying ShapeGeometry object(s)
|
|
||||||
getMarkerGeom(shapes::AVec) = gadflyshape(map(get_shape, shapes))
|
|
||||||
getMarkerGeom(other) = gadflyshape(get_shape(other))
|
|
||||||
|
|
||||||
# getMarkerGeom(shape::Shape) = gadflyshape(shape)
|
|
||||||
# getMarkerGeom(shape::Symbol) = gadflyshape(_shapes[shape])
|
|
||||||
# getMarkerGeom(shapes::AVec) = gadflyshape(map(gadflyshape, shapes)) # map(getMarkerGeom, shapes)
|
|
||||||
function getMarkerGeom(plotattributes::KW)
|
|
||||||
if plotattributes[:seriestype] == :shape
|
|
||||||
Gadfly.Geom.polygon(fill = true, preserve_order = true)
|
|
||||||
else
|
|
||||||
getMarkerGeom(plotattributes[:markershape])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getGadflyMarkerTheme(plotattributes::KW, attr::KW)
|
|
||||||
c = getColor(plotattributes[:markercolor])
|
|
||||||
α = plotattributes[:markeralpha]
|
|
||||||
if α != nothing
|
|
||||||
c = RGBA(RGB(c), α)
|
|
||||||
end
|
|
||||||
|
|
||||||
ms = plotattributes[:markersize]
|
|
||||||
ms = if typeof(ms) <: AVec
|
|
||||||
@warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))")
|
|
||||||
mean(ms) * Gadfly.px
|
|
||||||
else
|
|
||||||
ms * Gadfly.px
|
|
||||||
end
|
|
||||||
|
|
||||||
Gadfly.Theme(;
|
|
||||||
default_color = c,
|
|
||||||
default_point_size = ms,
|
|
||||||
discrete_highlight_color = c -> RGB(getColor(plotattributes[:markerstrokecolor])),
|
|
||||||
highlight_width = plotattributes[:markerstrokewidth] * Gadfly.px,
|
|
||||||
line_width = plotattributes[:markerstrokewidth] * Gadfly.px,
|
|
||||||
# get_extra_theme_args(plotattributes, :markerstrokestyle)...
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
function addGadflyContColorScale(plt::Plot{GadflyBackend}, c)
|
|
||||||
plt.attr[:colorbar] == :none && return
|
|
||||||
if !isa(c, ColorGradient)
|
|
||||||
c = default_gradient()
|
|
||||||
end
|
|
||||||
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p))))
|
|
||||||
end
|
|
||||||
|
|
||||||
function addGadflyMarker!(plt::Plot, numlayers::Int, plotattributes::KW, attr::KW, geoms...)
|
|
||||||
gfargs = vcat(geoms..., getGadflyMarkerTheme(plotattributes, attr), getMarkerGeom(plotattributes))
|
|
||||||
kwargs = KW()
|
|
||||||
|
|
||||||
# handle continuous color scales for the markers
|
|
||||||
zcolor = plotattributes[:marker_z]
|
|
||||||
if zcolor != nothing && typeof(zcolor) <: AVec
|
|
||||||
kwargs[:color] = zcolor
|
|
||||||
addGadflyContColorScale(plt, plotattributes[:markercolor])
|
|
||||||
end
|
|
||||||
|
|
||||||
Gadfly.layer(gfargs...; x = plotattributes[:x], y = plotattributes[:y], order=numlayers, kwargs...)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function addToGadflyLegend(plt::Plot, plotattributes::KW)
|
|
||||||
if plt.attr[:legend] != :none && plotattributes[:label] != ""
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
|
|
||||||
# add the legend if needed
|
|
||||||
if all(g -> !isa(g, Gadfly.Guide.ManualColorKey), gplt.guides)
|
|
||||||
pushfirst!(gplt.guides, Gadfly.Guide.manual_color_key("", AbstractString[], Color[]))
|
|
||||||
end
|
|
||||||
|
|
||||||
# now add the series to the legend
|
|
||||||
for guide in gplt.guides
|
|
||||||
if isa(guide, Gadfly.Guide.ManualColorKey)
|
|
||||||
# TODO: there's a BUG in gadfly if you pass in the same color more than once,
|
|
||||||
# since gadfly will call unique(colors), but doesn't also merge the rows that match
|
|
||||||
# Should ensure from this side that colors which are the same are merged together
|
|
||||||
|
|
||||||
c = getColor(plotattributes[plotattributes[:markershape] == :none ? :linecolor : :markercolor])
|
|
||||||
foundit = false
|
|
||||||
|
|
||||||
# extend the label if we found this color
|
|
||||||
for i in 1:length(guide.colors)
|
|
||||||
if RGB(c) == guide.colors[i]
|
|
||||||
guide.labels[i] *= ", " * plotattributes[:label]
|
|
||||||
foundit = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# didn't find the color, so add a new entry into the legend
|
|
||||||
if !foundit
|
|
||||||
push!(guide.labels, plotattributes[:label])
|
|
||||||
push!(guide.colors, c)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
getGadflySmoothing(smooth::Bool) = smooth ? [Gadfly.Geom.smooth(method=:lm)] : Any[]
|
|
||||||
getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=float(smooth))]
|
|
||||||
|
|
||||||
|
|
||||||
function addGadflySeries!(plt::Plot, plotattributes::KW)
|
|
||||||
layers = Gadfly.Layer[]
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
|
|
||||||
# add a regression line?
|
|
||||||
# TODO: make more flexible
|
|
||||||
smooth = getGadflySmoothing(plotattributes[:smooth])
|
|
||||||
|
|
||||||
# lines
|
|
||||||
geom = getLineGeom(plotattributes)
|
|
||||||
if geom != nothing
|
|
||||||
prepend!(layers, addGadflyLine!(plt, length(gplt.layers), plotattributes, geom, smooth...))
|
|
||||||
smooth = Any[] # don't add a regression for markers too
|
|
||||||
end
|
|
||||||
|
|
||||||
# special handling for ohlc and scatter
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
# if st == :ohlc
|
|
||||||
# error("Haven't re-implemented after refactoring")
|
|
||||||
if st in (:histogram2d, :hexbin) && (isa(plotattributes[:fillcolor], ColorGradient) || isa(plotattributes[:fillcolor], ColorFunction))
|
|
||||||
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(plotattributes[:fillcolor], p))))
|
|
||||||
elseif st == :scatter && plotattributes[:markershape] == :none
|
|
||||||
plotattributes[:markershape] = :circle
|
|
||||||
end
|
|
||||||
|
|
||||||
# markers
|
|
||||||
if plotattributes[:markershape] != :none || st == :shape
|
|
||||||
prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), plotattributes, plt.attr, smooth...))
|
|
||||||
end
|
|
||||||
|
|
||||||
st in (:histogram2d, :hexbin, :contour) || addToGadflyLegend(plt, plotattributes)
|
|
||||||
|
|
||||||
# now save the layers that apply to this series
|
|
||||||
plotattributes[:gadflylayers] = layers
|
|
||||||
prepend!(gplt.layers, layers)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# NOTE: I'm leaving this here and commented out just in case I want to implement again... it was hacky code to create multi-colored line segments
|
|
||||||
|
|
||||||
# # colorgroup
|
|
||||||
# z = plotattributes[:z]
|
|
||||||
|
|
||||||
# # handle line segments of different colors
|
|
||||||
# cscheme = plotattributes[:linecolor]
|
|
||||||
# if isa(cscheme, ColorVector)
|
|
||||||
# # create a color scale, and set the color group to the index of the color
|
|
||||||
# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...))
|
|
||||||
|
|
||||||
# # this is super weird, but... oh well... for some reason this creates n separate line segments...
|
|
||||||
# # create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y)
|
|
||||||
# # then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n]
|
|
||||||
# csindices = Int[mod1(i,length(cscheme.v)) for i in 1:length(plotattributes[:y])]
|
|
||||||
# cs = collect(repeat(csindices', 2, 1))[1:end-1]
|
|
||||||
# grp = collect(repeat((1:length(plotattributes[:y]))', 2, 1))[1:end-1]
|
|
||||||
# plotattributes[:x], plotattributes[:y] = map(createSegments, (plotattributes[:x], plotattributes[:y]))
|
|
||||||
# colorgroup = [(:linecolor, cs), (:group, grp)]
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function addGadflyTicksGuide(gplt, ticks, isx::Bool)
|
|
||||||
ticks == :auto && return
|
|
||||||
|
|
||||||
# remove the ticks?
|
|
||||||
if ticks in (:none, false, nothing)
|
|
||||||
return addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
|
|
||||||
end
|
|
||||||
|
|
||||||
ttype = ticksType(ticks)
|
|
||||||
|
|
||||||
# just the values... put ticks here, but use standard labels
|
|
||||||
if ttype == :ticks
|
|
||||||
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
|
|
||||||
replaceType(gplt.guides, gtype(ticks = collect(ticks)))
|
|
||||||
|
|
||||||
# set the ticks and the labels
|
|
||||||
# Note: this is pretty convoluted, but I think it works. We set the ticks using Gadfly.Guide,
|
|
||||||
# and then set the label function (wraps a dict lookup) through a continuous Gadfly.Scale.
|
|
||||||
elseif ttype == :ticks_and_labels
|
|
||||||
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
|
|
||||||
replaceType(gplt.guides, gtype(ticks = collect(ticks[1])))
|
|
||||||
|
|
||||||
# # TODO add xtick_label function (given tick, return label??)
|
|
||||||
# # Scale.x_discrete(; labels=nothing, levels=nothing, order=nothing)
|
|
||||||
# filterGadflyScale(gplt, isx)
|
|
||||||
# gfunc = isx ? Gadfly.Scale.x_discrete : Gadfly.Scale.y_discrete
|
|
||||||
# labelmap = Dict(zip(ticks...))
|
|
||||||
# labelfunc = val -> labelmap[val]
|
|
||||||
# push!(gplt.scales, gfunc(levels = collect(ticks[1]), labels = labelfunc))
|
|
||||||
|
|
||||||
filterGadflyScale(gplt, isx)
|
|
||||||
gfunc = isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous
|
|
||||||
labelmap = Dict(zip(ticks...))
|
|
||||||
labelfunc = val -> labelmap[val]
|
|
||||||
push!(gplt.scales, gfunc(labels = labelfunc))
|
|
||||||
|
|
||||||
else
|
|
||||||
error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
continuousAndSameAxis(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y)
|
|
||||||
filterGadflyScale(gplt, isx::Bool) = filter!(scale -> !continuousAndSameAxis(scale, isx), gplt.scales)
|
|
||||||
|
|
||||||
|
|
||||||
function getGadflyScaleFunction(plotattributes::KW, isx::Bool)
|
|
||||||
scalekey = isx ? :xscale : :yscale
|
|
||||||
hasScaleKey = haskey(plotattributes, scalekey)
|
|
||||||
if hasScaleKey
|
|
||||||
scale = plotattributes[scalekey]
|
|
||||||
scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey, log
|
|
||||||
scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey, log2
|
|
||||||
scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey, log10
|
|
||||||
scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey, asinh
|
|
||||||
scale == :sqrt && return isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt, hasScaleKey, sqrt
|
|
||||||
end
|
|
||||||
isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous, hasScaleKey, identity
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function addGadflyLimitsScale(gplt, plotattributes::KW, isx::Bool)
|
|
||||||
gfunc, hasScaleKey, func = getGadflyScaleFunction(plotattributes, isx)
|
|
||||||
|
|
||||||
# do we want to add min/max limits for the axis?
|
|
||||||
limsym = isx ? :xlims : :ylims
|
|
||||||
limargs = Any[]
|
|
||||||
|
|
||||||
# map :auto to nothing, otherwise add to limargs
|
|
||||||
lims = get(plotattributes, limsym, :auto)
|
|
||||||
if lims == :auto
|
|
||||||
lims = nothing
|
|
||||||
else
|
|
||||||
if limsType(lims) == :limits
|
|
||||||
push!(limargs, (:minvalue, min(lims...)))
|
|
||||||
push!(limargs, (:maxvalue, max(lims...)))
|
|
||||||
else
|
|
||||||
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# replace any current scales with this one
|
|
||||||
if hasScaleKey || !isempty(limargs)
|
|
||||||
filterGadflyScale(gplt, isx)
|
|
||||||
push!(gplt.scales, gfunc(; limargs...))
|
|
||||||
end
|
|
||||||
|
|
||||||
lims, func
|
|
||||||
end
|
|
||||||
|
|
||||||
function updateGadflyAxisFlips(gplt, plotattributes::KW, xlims, ylims, xfunc, yfunc)
|
|
||||||
if isa(gplt.coord, Gadfly.Coord.Cartesian)
|
|
||||||
gplt.coord = Gadfly.Coord.cartesian(
|
|
||||||
gplt.coord.xvars,
|
|
||||||
gplt.coord.yvars;
|
|
||||||
xmin = xlims == nothing ? gplt.coord.xmin : xfunc(minimum(xlims)),
|
|
||||||
xmax = xlims == nothing ? gplt.coord.xmax : xfunc(maximum(xlims)),
|
|
||||||
ymin = ylims == nothing ? gplt.coord.ymin : yfunc(minimum(ylims)),
|
|
||||||
ymax = ylims == nothing ? gplt.coord.ymax : yfunc(maximum(ylims)),
|
|
||||||
xflip = get(plotattributes, :xflip, gplt.coord.xflip),
|
|
||||||
yflip = get(plotattributes, :yflip, gplt.coord.yflip),
|
|
||||||
fixed = gplt.coord.fixed,
|
|
||||||
aspect_ratio = gplt.coord.aspect_ratio,
|
|
||||||
raster = gplt.coord.raster
|
|
||||||
)
|
|
||||||
else
|
|
||||||
gplt.coord = Gadfly.Coord.Cartesian(
|
|
||||||
xflip = get(plotattributes, :xflip, false),
|
|
||||||
yflip = get(plotattributes, :yflip, false)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function findGuideAndSet(gplt, t::DataType, args...; kw...)
|
|
||||||
for (i,guide) in enumerate(gplt.guides)
|
|
||||||
if isa(guide, t)
|
|
||||||
gplt.guides[i] = t(args...; kw...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function updateGadflyGuides(plt::Plot, plotattributes::KW)
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
haskey(plotattributes, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, string(plotattributes[:title]))
|
|
||||||
haskey(plotattributes, :xguide) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, string(plotattributes[:xguide]))
|
|
||||||
haskey(plotattributes, :yguide) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, string(plotattributes[:yguide]))
|
|
||||||
|
|
||||||
xlims, xfunc = addGadflyLimitsScale(gplt, plotattributes, true)
|
|
||||||
ylims, yfunc = addGadflyLimitsScale(gplt, plotattributes, false)
|
|
||||||
|
|
||||||
ticks = get(plotattributes, :xticks, :auto)
|
|
||||||
if ticks == :none
|
|
||||||
_remove_axis(plt, true)
|
|
||||||
else
|
|
||||||
addGadflyTicksGuide(gplt, ticks, true)
|
|
||||||
end
|
|
||||||
ticks = get(plotattributes, :yticks, :auto)
|
|
||||||
if ticks == :none
|
|
||||||
_remove_axis(plt, false)
|
|
||||||
else
|
|
||||||
addGadflyTicksGuide(gplt, ticks, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
updateGadflyAxisFlips(gplt, plotattributes, xlims, ylims, xfunc, yfunc)
|
|
||||||
end
|
|
||||||
|
|
||||||
function updateGadflyPlotTheme(plt::Plot, plotattributes::KW)
|
|
||||||
kwargs = KW()
|
|
||||||
|
|
||||||
# colors
|
|
||||||
insidecolor, gridcolor, textcolor, guidecolor, legendcolor =
|
|
||||||
map(s -> getColor(plotattributes[s]), (
|
|
||||||
:background_color_inside,
|
|
||||||
:foreground_color_grid,
|
|
||||||
:foreground_color_text,
|
|
||||||
:foreground_color_guide,
|
|
||||||
:foreground_color_legend
|
|
||||||
))
|
|
||||||
|
|
||||||
# # hide the legend?
|
|
||||||
leg = plotattributes[plotattributes[:legend] == :none ? :colorbar : :legend]
|
|
||||||
if leg != :best
|
|
||||||
kwargs[:key_position] = leg == :inside ? :right : leg
|
|
||||||
end
|
|
||||||
|
|
||||||
if !get(plotattributes, :grid, true)
|
|
||||||
kwargs[:grid_color] = gridcolor
|
|
||||||
end
|
|
||||||
|
|
||||||
# fonts
|
|
||||||
tfont, gfont, lfont = plotattributes[:tickfont], plotattributes[:guidefont], plotattributes[:legendfont]
|
|
||||||
|
|
||||||
getGadflyContext(plt).theme = Gadfly.Theme(;
|
|
||||||
background_color = insidecolor,
|
|
||||||
minor_label_color = textcolor,
|
|
||||||
minor_label_font = tfont.family,
|
|
||||||
minor_label_font_size = tfont.pointsize * Gadfly.pt,
|
|
||||||
major_label_color = guidecolor,
|
|
||||||
major_label_font = gfont.family,
|
|
||||||
major_label_font_size = gfont.pointsize * Gadfly.pt,
|
|
||||||
key_title_color = guidecolor,
|
|
||||||
key_title_font = gfont.family,
|
|
||||||
key_title_font_size = gfont.pointsize * Gadfly.pt,
|
|
||||||
key_label_color = legendcolor,
|
|
||||||
key_label_font = lfont.family,
|
|
||||||
key_label_font_size = lfont.pointsize * Gadfly.pt,
|
|
||||||
plot_padding = 1 * Gadfly.mm,
|
|
||||||
kwargs...
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function createGadflyAnnotationObject(x, y, val::AbstractString)
|
|
||||||
Gadfly.Guide.annotation(Compose.compose(
|
|
||||||
Compose.context(),
|
|
||||||
Compose.text(x, y, val)
|
|
||||||
))
|
|
||||||
end
|
|
||||||
|
|
||||||
function createGadflyAnnotationObject(x, y, txt::PlotText)
|
|
||||||
halign = (txt.font.halign == :hcenter ? Compose.hcenter : (txt.font.halign == :left ? Compose.hleft : Compose.hright))
|
|
||||||
valign = (txt.font.valign == :vcenter ? Compose.vcenter : (txt.font.valign == :top ? Compose.vtop : Compose.vbottom))
|
|
||||||
rotations = (txt.font.rotation == 0.0 ? [] : [Compose.Rotation(txt.font.rotation, Compose.Point(Compose.x_measure(x), Compose.y_measure(y)))])
|
|
||||||
Gadfly.Guide.annotation(Compose.compose(
|
|
||||||
Compose.context(),
|
|
||||||
Compose.text(x, y, txt.str, halign, valign, rotations...),
|
|
||||||
Compose.font(string(txt.font.family)),
|
|
||||||
Compose.fontsize(txt.font.pointsize * Gadfly.pt),
|
|
||||||
Compose.stroke(txt.font.color),
|
|
||||||
Compose.fill(txt.font.color)
|
|
||||||
))
|
|
||||||
end
|
|
||||||
|
|
||||||
function _add_annotations(plt::Plot{GadflyBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
|
||||||
for ann in anns
|
|
||||||
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# create a blank Gadfly.Plot object
|
|
||||||
# function _create_plot(pkg::GadflyBackend, plotattributes::KW)
|
|
||||||
# gplt = createGadflyPlotObject(plotattributes)
|
|
||||||
# Plot(gplt, pkg, 0, plotattributes, KW[])
|
|
||||||
# end
|
|
||||||
function _create_backend_figure(plt::Plot{GadflyBackend})
|
|
||||||
createGadflyPlotObject(plt.attr)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# plot one data series
|
|
||||||
# function _series_added(::GadflyBackend, plt::Plot, plotattributes::KW)
|
|
||||||
function _series_added(plt::Plot{GadflyBackend}, series::Series)
|
|
||||||
# first clear out the temporary layer
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
if gplt.layers[1].geom.tag == :remove
|
|
||||||
gplt.layers = gplt.layers[2:end]
|
|
||||||
end
|
|
||||||
|
|
||||||
addGadflySeries!(plt, series.plotattributes)
|
|
||||||
# push!(plt.seriesargs, plotattributes)
|
|
||||||
# plt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function _update_plot_object(plt::Plot{GadflyBackend}, plotattributes::KW)
|
|
||||||
updateGadflyGuides(plt, plotattributes)
|
|
||||||
updateGadflyPlotTheme(plt, plotattributes)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# accessors for x/y data
|
|
||||||
|
|
||||||
# TODO: need to save all the layer indices which apply to this series
|
|
||||||
function getGadflyMappings(plt::Plot, i::Integer)
|
|
||||||
@assert i > 0 && i <= plt.n
|
|
||||||
mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]]
|
|
||||||
end
|
|
||||||
|
|
||||||
function getxy(plt::Plot{GadflyBackend}, i::Integer)
|
|
||||||
mapping = getGadflyMappings(plt, i)[1]
|
|
||||||
mapping[:x], mapping[:y]
|
|
||||||
end
|
|
||||||
|
|
||||||
function setxy!(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
|
||||||
for mapping in getGadflyMappings(plt, i)
|
|
||||||
mapping[:x], mapping[:y] = xy
|
|
||||||
end
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# # create the underlying object (each backend will do this differently)
|
|
||||||
# function _create_subplot(subplt::Subplot{GadflyBackend}, isbefore::Bool)
|
|
||||||
# isbefore && return false # wait until after plotting to create the subplots
|
|
||||||
# subplt.o = nothing
|
|
||||||
# true
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
function _remove_axis(plt::Plot{GadflyBackend}, isx::Bool)
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
|
|
||||||
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
function _expand_limits(lims, plt::Plot{GadflyBackend}, isx::Bool)
|
|
||||||
for l in getGadflyContext(plt).layers
|
|
||||||
_expand_limits(lims, l.mapping[isx ? :x : :y])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
getGadflyContext(plt::Plot{GadflyBackend}) = plt.o
|
|
||||||
# getGadflyContext(subplt::Subplot{GadflyBackend}) = buildGadflySubplotContext(subplt)
|
|
||||||
|
|
||||||
# # create my Compose.Context grid by hstacking and vstacking the Gadfly.Plot objects
|
|
||||||
# function buildGadflySubplotContext(subplt::Subplot)
|
|
||||||
# rows = Any[]
|
|
||||||
# row = Any[]
|
|
||||||
# for (i,(r,c)) in enumerate(subplt.layout)
|
|
||||||
#
|
|
||||||
# # add the Plot object to the row
|
|
||||||
# push!(row, getGadflyContext(subplt.plts[i]))
|
|
||||||
#
|
|
||||||
# # add the row
|
|
||||||
# if c == ncols(subplt.layout, r)
|
|
||||||
# push!(rows, Gadfly.hstack(row...))
|
|
||||||
# row = Any[]
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # stack the rows
|
|
||||||
# Gadfly.vstack(rows...)
|
|
||||||
# end
|
|
||||||
|
|
||||||
setGadflyDisplaySize(w,h) = Compose.set_default_graphic_size(w * Compose.px, h * Compose.px)
|
|
||||||
setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.attr[:size]...)
|
|
||||||
# setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getattr(subplt, 1)[:size]...)
|
|
||||||
# -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function doshow(io::IO, func, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
setGadflyDisplaySize(plt)
|
|
||||||
Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
|
|
||||||
end
|
|
||||||
|
|
||||||
getGadflyWriteFunc(::MIME"image/png") = Gadfly.PNG
|
|
||||||
getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG
|
|
||||||
# getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS
|
|
||||||
getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF
|
|
||||||
getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS
|
|
||||||
getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF
|
|
||||||
getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m)
|
|
||||||
|
|
||||||
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex")
|
|
||||||
@eval function Base.show(io::IO, ::$mime, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
|
|
||||||
func = getGadflyWriteFunc($mime())
|
|
||||||
doshow(io, func, plt)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Base.display(::PlotsDisplay, plt::Plot{GadflyBackend})
|
|
||||||
setGadflyDisplaySize(plt.attr[:size]...)
|
|
||||||
display(plt.o)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# function Base.display(::PlotsDisplay, subplt::Subplot{GadflyBackend})
|
|
||||||
# setGadflyDisplaySize(getattr(subplt,1)[:size]...)
|
|
||||||
# ctx = buildGadflySubplotContext(subplt)
|
|
||||||
#
|
|
||||||
# # taken from Gadfly since I couldn't figure out how to do it directly
|
|
||||||
#
|
|
||||||
# filename = string(Gadfly.tempname(), ".html")
|
|
||||||
# output = open(filename, "w")
|
|
||||||
#
|
|
||||||
# plot_output = IOBuffer()
|
|
||||||
# Gadfly.draw(Gadfly.SVGJS(plot_output, Compose.default_graphic_width,
|
|
||||||
# Compose.default_graphic_height, false), ctx)
|
|
||||||
# plotsvg = takebuf_string(plot_output)
|
|
||||||
#
|
|
||||||
# write(output,
|
|
||||||
# """
|
|
||||||
# <!DOCTYPE html>
|
|
||||||
# <html>
|
|
||||||
# <head>
|
|
||||||
# <title>Gadfly Plot</title>
|
|
||||||
# <meta charset="utf-8">
|
|
||||||
# </head>
|
|
||||||
# <body>
|
|
||||||
# <script charset="utf-8">
|
|
||||||
# $(readall(Compose.snapsvgjs))
|
|
||||||
# </script>
|
|
||||||
# <script charset="utf-8">
|
|
||||||
# $(readall(Gadfly.gadflyjs))
|
|
||||||
# </script>
|
|
||||||
# $(plotsvg)
|
|
||||||
# </body>
|
|
||||||
# </html>
|
|
||||||
# """)
|
|
||||||
# close(output)
|
|
||||||
# Gadfly.open_file(filename)
|
|
||||||
# end
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
# Geometry which displays arbitrary shapes at given (x, y) positions.
|
|
||||||
# note: vertices is a list of shapes
|
|
||||||
struct ShapeGeometry <: Gadfly.GeometryElement
|
|
||||||
vertices::AbstractVector #{Tuple{Float64,Float64}}
|
|
||||||
tag::Symbol
|
|
||||||
|
|
||||||
function ShapeGeometry(shape; tag::Symbol=Gadfly.Geom.empty_tag)
|
|
||||||
new(shape, tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO: add for PR
|
|
||||||
# const shape = ShapeGeometry
|
|
||||||
|
|
||||||
|
|
||||||
function Gadfly.element_aesthetics(::ShapeGeometry)
|
|
||||||
[:x, :y, :size, :color]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# Generate a form for a shape geometry.
|
|
||||||
#
|
|
||||||
# Args:
|
|
||||||
# geom: shape geometry.
|
|
||||||
# theme: the plot's theme.
|
|
||||||
# aes: aesthetics.
|
|
||||||
#
|
|
||||||
# Returns:
|
|
||||||
# A compose Form.
|
|
||||||
#
|
|
||||||
function Gadfly.render(geom::ShapeGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics)
|
|
||||||
|
|
||||||
# TODO: add for PR
|
|
||||||
# Gadfly.assert_aesthetics_defined("Geom.shape", aes, :x, :y)
|
|
||||||
# Gadfly.assert_aesthetics_equal_length("Geom.shape", aes,
|
|
||||||
# element_aesthetics(geom)...)
|
|
||||||
|
|
||||||
default_aes = Gadfly.Aesthetics()
|
|
||||||
default_aes.color = Gadfly.DataFrames.PooledDataArray(RGBA{Float32}[theme.default_color])
|
|
||||||
default_aes.size = Compose.Measure[theme.default_point_size]
|
|
||||||
aes = Gadfly.inherit(aes, default_aes)
|
|
||||||
|
|
||||||
lw_hover_scale = 10
|
|
||||||
lw_ratio = theme.line_width / aes.size[1]
|
|
||||||
|
|
||||||
aes_x, aes_y = Gadfly.concretize(aes.x, aes.y)
|
|
||||||
|
|
||||||
ctx = Compose.compose!(
|
|
||||||
Compose.context(),
|
|
||||||
make_polygon(geom, aes.x, aes.y, aes.size),
|
|
||||||
Compose.fill(aes.color),
|
|
||||||
Compose.linewidth(theme.highlight_width))
|
|
||||||
|
|
||||||
if aes.color_key_continuous != nothing && aes.color_key_continuous
|
|
||||||
Compose.compose!(ctx,
|
|
||||||
Compose.stroke(map(theme.continuous_highlight_color, aes.color)))
|
|
||||||
else
|
|
||||||
Compose.compose!(ctx,
|
|
||||||
Compose.stroke(map(theme.discrete_highlight_color, aes.color)),
|
|
||||||
Compose.svgclass([Gadfly.svg_color_class_from_label(Gadfly.escape_id(aes.color_label([c])[1]))
|
|
||||||
for c in aes.color]))
|
|
||||||
end
|
|
||||||
|
|
||||||
return Compose.compose!(Compose.context(order=4), Compose.svgclass("geometry"), ctx)
|
|
||||||
end
|
|
||||||
|
|
||||||
function gadflyshape(sv::Shape)
|
|
||||||
ShapeGeometry(Any[vertices(sv)])
|
|
||||||
end
|
|
||||||
|
|
||||||
function gadflyshape(sv::AVec{Shape})
|
|
||||||
ShapeGeometry(Any[vertices(s) for s in sv])
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# create a Compose context given a ShapeGeometry and the xs/ys/sizes
|
|
||||||
function make_polygon(geom::ShapeGeometry, xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
||||||
n = max(length(xs), length(ys), length(rs))
|
|
||||||
T = Tuple{Compose.Measure, Compose.Measure}
|
|
||||||
polys = Array(Vector{T}, n)
|
|
||||||
for i in 1:n
|
|
||||||
x = Compose.x_measure(xs[mod1(i, length(xs))])
|
|
||||||
y = Compose.y_measure(ys[mod1(i, length(ys))])
|
|
||||||
r = rs[mod1(i, length(rs))]
|
|
||||||
polys[i] = T[(x + r * sx, y + r * sy) for (sx,sy) in _cycle(geom.vertices, i)]
|
|
||||||
end
|
|
||||||
Gadfly.polygon(polys, geom.tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------------------
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
|
|
||||||
# https://github.com/JuliaGraphics/Immerse.jl
|
|
||||||
|
|
||||||
supported_attrs(::ImmerseBackend) = supported_attrs(GadflyBackend())
|
|
||||||
supported_types(::ImmerseBackend) = supported_types(GadflyBackend())
|
|
||||||
supported_styles(::ImmerseBackend) = supported_styles(GadflyBackend())
|
|
||||||
supported_markers(::ImmerseBackend) = supported_markers(GadflyBackend())
|
|
||||||
supported_scales(::ImmerseBackend) = supported_scales(GadflyBackend())
|
|
||||||
is_subplot_supported(::ImmerseBackend) = true
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function _initialize_backend(::ImmerseBackend; kw...)
|
|
||||||
@eval begin
|
|
||||||
import Immerse, Gadfly, Compose, Gtk
|
|
||||||
export Immerse, Gadfly, Compose, Gtk
|
|
||||||
include(joinpath(dirname(@__FILE__), "gadfly_shapes.jl"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function createImmerseFigure(plotattributes::KW)
|
|
||||||
w,h = plotattributes[:size]
|
|
||||||
figidx = Immerse.figure(; name = plotattributes[:window_title], width = w, height = h)
|
|
||||||
Immerse.Figure(figidx)
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# create a blank Gadfly.Plot object
|
|
||||||
# function _create_plot(pkg::ImmerseBackend, plotattributes::KW)
|
|
||||||
# # create the underlying Gadfly.Plot object
|
|
||||||
# gplt = createGadflyPlotObject(plotattributes)
|
|
||||||
#
|
|
||||||
# # save both the Immerse.Figure and the Gadfly.Plot
|
|
||||||
# Plot((nothing,gplt), pkg, 0, plotattributes, KW[])
|
|
||||||
# end
|
|
||||||
function _create_backend_figure(plt::Plot{ImmerseBackend})
|
|
||||||
(nothing, createGadflyPlotObject(plt.attr))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# # plot one data series
|
|
||||||
# function _series_added(::ImmerseBackend, plt::Plot, plotattributes::KW)
|
|
||||||
# addGadflySeries!(plt, plotattributes)
|
|
||||||
# push!(plt.seriesargs, plotattributes)
|
|
||||||
# plt
|
|
||||||
# end
|
|
||||||
|
|
||||||
function _series_added(plt::Plot{ImmerseBackend}, series::Series)
|
|
||||||
addGadflySeries!(plt, series.plotattributes)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function _update_plot_object(plt::Plot{ImmerseBackend}, plotattributes::KW)
|
|
||||||
updateGadflyGuides(plt, plotattributes)
|
|
||||||
updateGadflyPlotTheme(plt, plotattributes)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function _add_annotations(plt::Plot{ImmerseBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
|
||||||
for ann in anns
|
|
||||||
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# accessors for x/y data
|
|
||||||
|
|
||||||
function getxy(plt::Plot{ImmerseBackend}, i::Integer)
|
|
||||||
mapping = getGadflyMappings(plt, i)[1]
|
|
||||||
mapping[:x], mapping[:y]
|
|
||||||
end
|
|
||||||
|
|
||||||
function setxy!(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
|
||||||
for mapping in getGadflyMappings(plt, i)
|
|
||||||
mapping[:x], mapping[:y] = xy
|
|
||||||
end
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# function _create_subplot(subplt::Subplot{ImmerseBackend}, isbefore::Bool)
|
|
||||||
# return false
|
|
||||||
# # isbefore && return false
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# function showSubplotObject(subplt::Subplot{ImmerseBackend})
|
|
||||||
# # create the Gtk window with vertical box vsep
|
|
||||||
# plotattributes = getattr(subplt,1)
|
|
||||||
# w,h = plotattributes[:size]
|
|
||||||
# vsep = Gtk.GtkBoxLeaf(:v)
|
|
||||||
# win = Gtk.GtkWindowLeaf(vsep, plotattributes[:window_title], w, h)
|
|
||||||
#
|
|
||||||
# figindices = []
|
|
||||||
# row = Gtk.GtkBoxLeaf(:h)
|
|
||||||
# push!(vsep, row)
|
|
||||||
# for (i,(r,c)) in enumerate(subplt.layout)
|
|
||||||
# plt = subplt.plts[i]
|
|
||||||
#
|
|
||||||
# # get the components... box is the main plot GtkBox, and canvas is the GtkCanvas where it's plotted
|
|
||||||
# box, toolbar, canvas = Immerse.createPlotGuiComponents()
|
|
||||||
#
|
|
||||||
# # add the plot's box to the row
|
|
||||||
# push!(row, box)
|
|
||||||
#
|
|
||||||
# # create the figure and store the index returned for destruction later
|
|
||||||
# figidx = Immerse.figure(canvas)
|
|
||||||
# push!(figindices, figidx)
|
|
||||||
#
|
|
||||||
# fig = Immerse.figure(figidx)
|
|
||||||
# plt.o = (fig, plt.o[2])
|
|
||||||
#
|
|
||||||
# # add the row
|
|
||||||
# if c == ncols(subplt.layout, r)
|
|
||||||
# row = Gtk.GtkBoxLeaf(:h)
|
|
||||||
# push!(vsep, row)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # destructor... clean up plots
|
|
||||||
# Gtk.on_signal_destroy((x...) -> ([Immerse.dropfig(Immerse._display,i) for i in figindices]; subplt.o = nothing), win)
|
|
||||||
#
|
|
||||||
# subplt.o = win
|
|
||||||
# true
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
function _remove_axis(plt::Plot{ImmerseBackend}, isx::Bool)
|
|
||||||
gplt = getGadflyContext(plt)
|
|
||||||
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
|
|
||||||
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
|
|
||||||
end
|
|
||||||
|
|
||||||
function _expand_limits(lims, plt::Plot{ImmerseBackend}, isx::Bool)
|
|
||||||
for l in getGadflyContext(plt).layers
|
|
||||||
_expand_limits(lims, l.mapping[isx ? :x : :y])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
getGadflyContext(plt::Plot{ImmerseBackend}) = plt.o[2]
|
|
||||||
# getGadflyContext(subplt::Subplot{ImmerseBackend}) = buildGadflySubplotContext(subplt)
|
|
||||||
|
|
||||||
|
|
||||||
function Base.display(::PlotsDisplay, plt::Plot{ImmerseBackend})
|
|
||||||
|
|
||||||
fig, gplt = plt.o
|
|
||||||
if fig == nothing
|
|
||||||
fig = createImmerseFigure(plt.attr)
|
|
||||||
Gtk.on_signal_destroy((x...) -> (Immerse.dropfig(Immerse._display, fig.figno); plt.o = (nothing,gplt)), fig.canvas)
|
|
||||||
plt.o = (fig, gplt)
|
|
||||||
end
|
|
||||||
|
|
||||||
Immerse.figure(fig.figno; displayfig = false)
|
|
||||||
display(gplt)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# function Base.display(::PlotsDisplay, subplt::Subplot{ImmerseBackend})
|
|
||||||
#
|
|
||||||
# # if we haven't created the window yet, do it
|
|
||||||
# if subplt.o == nothing
|
|
||||||
# showSubplotObject(subplt)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # display the plots by creating a fresh Immerse.Figure object from the GtkCanvas and Gadfly.Plot
|
|
||||||
# for plt in subplt.plts
|
|
||||||
# fig, gplt = plt.o
|
|
||||||
# Immerse.figure(fig.figno; displayfig = false)
|
|
||||||
# display(gplt)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # o is the window... show it
|
|
||||||
# showall(subplt.o)
|
|
||||||
# end
|
|
||||||
@ -1,308 +0,0 @@
|
|||||||
|
|
||||||
# https://github.com/tbreloff/Qwt.jl
|
|
||||||
|
|
||||||
|
|
||||||
supported_attrs(::QwtBackend) = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:linecolor,
|
|
||||||
:fillrange,
|
|
||||||
:fillcolor,
|
|
||||||
:label,
|
|
||||||
:legend,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linestyle,
|
|
||||||
:linewidth,
|
|
||||||
:markershape,
|
|
||||||
:markercolor,
|
|
||||||
:markersize,
|
|
||||||
:bins,
|
|
||||||
:pos,
|
|
||||||
:title,
|
|
||||||
:window_title,
|
|
||||||
:guide, :lims, :ticks, :scale,
|
|
||||||
])
|
|
||||||
supported_types(::QwtBackend) = [:path, :scatter, :hexbin, :bar]
|
|
||||||
supported_markers(::QwtBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :star8, :hexagon]
|
|
||||||
supported_scales(::QwtBackend) = [:identity, :log10]
|
|
||||||
is_subplot_supported(::QwtBackend) = true
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function _initialize_backend(::QwtBackend; kw...)
|
|
||||||
@eval begin
|
|
||||||
@warn("Qwt is no longer supported... many features will likely be broken.")
|
|
||||||
import Qwt
|
|
||||||
export Qwt
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# -------------------------------
|
|
||||||
|
|
||||||
const _qwtAliases = KW(
|
|
||||||
:bins => :heatmap_n,
|
|
||||||
:fillrange => :fillto,
|
|
||||||
:linewidth => :width,
|
|
||||||
:markershape => :marker,
|
|
||||||
:hexbin => :heatmap,
|
|
||||||
:path => :line,
|
|
||||||
:steppost => :step,
|
|
||||||
:steppre => :stepinverted,
|
|
||||||
:star5 => :star1,
|
|
||||||
:star8 => :star2,
|
|
||||||
)
|
|
||||||
|
|
||||||
function fixcolors(plotattributes::KW)
|
|
||||||
for (k,v) in plotattributes
|
|
||||||
if typeof(v) <: ColorScheme
|
|
||||||
plotattributes[k] = getColor(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function replaceQwtAliases(plotattributes, s)
|
|
||||||
if haskey(_qwtAliases, plotattributes[s])
|
|
||||||
plotattributes[s] = _qwtAliases[plotattributes[s]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function adjustQwtKeywords(plt::Plot{QwtBackend}, iscreating::Bool; kw...)
|
|
||||||
plotattributes = KW(kw)
|
|
||||||
st = plotattributes[:seriestype]
|
|
||||||
if st == :scatter
|
|
||||||
plotattributes[:seriestype] = :none
|
|
||||||
if plotattributes[:markershape] == :none
|
|
||||||
plotattributes[:markershape] = :circle
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif st in (:hline, :vline)
|
|
||||||
addLineMarker(plt, plotattributes)
|
|
||||||
plotattributes[:seriestype] = :none
|
|
||||||
plotattributes[:markershape] = :circle
|
|
||||||
plotattributes[:markersize] = 1
|
|
||||||
if st == :vline
|
|
||||||
plotattributes[:x], plotattributes[:y] = plotattributes[:y], plotattributes[:x]
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif !iscreating && st == :bar
|
|
||||||
plotattributes = barHack(; kw...)
|
|
||||||
elseif !iscreating && st == :histogram
|
|
||||||
plotattributes = barHack(; histogramHack(; kw...)...)
|
|
||||||
end
|
|
||||||
|
|
||||||
replaceQwtAliases(plotattributes, :seriestype)
|
|
||||||
replaceQwtAliases(plotattributes, :markershape)
|
|
||||||
|
|
||||||
for k in keys(plotattributes)
|
|
||||||
if haskey(_qwtAliases, k)
|
|
||||||
plotattributes[_qwtAliases[k]] = plotattributes[k]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
plotattributes[:x] = collect(plotattributes[:x])
|
|
||||||
plotattributes[:y] = collect(plotattributes[:y])
|
|
||||||
|
|
||||||
plotattributes
|
|
||||||
end
|
|
||||||
|
|
||||||
# function _create_plot(pkg::QwtBackend, plotattributes::KW)
|
|
||||||
function _create_backend_figure(plt::Plot{QwtBackend})
|
|
||||||
fixcolors(plt.attr)
|
|
||||||
dumpdict(plt.attr,"\n\n!!! plot")
|
|
||||||
o = Qwt.plot(zeros(0,0); plt.attr..., show=false)
|
|
||||||
# plt = Plot(o, pkg, 0, plotattributes, KW[])
|
|
||||||
# plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# function _series_added(::QwtBackend, plt::Plot, plotattributes::KW)
|
|
||||||
function _series_added(plt::Plot{QwtBackend}, series::Series)
|
|
||||||
plotattributes = adjustQwtKeywords(plt, false; series.plotattributes...)
|
|
||||||
fixcolors(plotattributes)
|
|
||||||
dumpdict(plotattributes,"\n\n!!! plot!")
|
|
||||||
Qwt.oplot(plt.o; plotattributes...)
|
|
||||||
# push!(plt.seriesargs, plotattributes)
|
|
||||||
# plt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function updateLimsAndTicks(plt::Plot{QwtBackend}, plotattributes::KW, isx::Bool)
|
|
||||||
lims = get(plotattributes, isx ? :xlims : :ylims, nothing)
|
|
||||||
ticks = get(plotattributes, isx ? :xticks : :yticks, nothing)
|
|
||||||
w = plt.o.widget
|
|
||||||
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
|
|
||||||
|
|
||||||
if typeof(lims) <: Union{Tuple,AVec} && length(lims) == 2
|
|
||||||
if isx
|
|
||||||
plt.o.autoscale_x = false
|
|
||||||
else
|
|
||||||
plt.o.autoscale_y = false
|
|
||||||
end
|
|
||||||
w[:setAxisScale](axisid, lims...)
|
|
||||||
end
|
|
||||||
|
|
||||||
if typeof(ticks) <: AbstractRange
|
|
||||||
if isx
|
|
||||||
plt.o.autoscale_x = false
|
|
||||||
else
|
|
||||||
plt.o.autoscale_y = false
|
|
||||||
end
|
|
||||||
w[:setAxisScale](axisid, float(minimum(ticks)), float(maximum(ticks)), float(step(ticks)))
|
|
||||||
elseif !(ticks in (nothing, :none, :auto))
|
|
||||||
@warn("Only Range types are supported for Qwt xticks/yticks. typeof(ticks)=$(typeof(ticks))")
|
|
||||||
end
|
|
||||||
|
|
||||||
# change the scale
|
|
||||||
scalesym = isx ? :xscale : :yscale
|
|
||||||
if haskey(plotattributes, scalesym)
|
|
||||||
scaletype = plotattributes[scalesym]
|
|
||||||
scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine())
|
|
||||||
# scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e))
|
|
||||||
# scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2))
|
|
||||||
scaletype == :log10 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLog10ScaleEngine())
|
|
||||||
scaletype in supported_scales() || @warn("Unsupported scale type: ", scaletype)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function _update_plot_object(plt::Plot{QwtBackend}, plotattributes::KW)
|
|
||||||
haskey(plotattributes, :title) && Qwt.title(plt.o, plotattributes[:title])
|
|
||||||
haskey(plotattributes, :xguide) && Qwt.xlabel(plt.o, plotattributes[:xguide])
|
|
||||||
haskey(plotattributes, :yguide) && Qwt.ylabel(plt.o, plotattributes[:yguide])
|
|
||||||
updateLimsAndTicks(plt, plotattributes, true)
|
|
||||||
updateLimsAndTicks(plt, plotattributes, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _update_plot_pos_size(plt::AbstractPlot{QwtBackend}, plotattributes::KW)
|
|
||||||
haskey(plotattributes, :size) && Qwt.resizewidget(plt.o, plotattributes[:size]...)
|
|
||||||
haskey(plotattributes, :pos) && Qwt.movewidget(plt.o, plotattributes[:pos]...)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle)))
|
|
||||||
function addLineMarker(plt::Plot{QwtBackend}, plotattributes::KW)
|
|
||||||
for yi in plotattributes[:y]
|
|
||||||
marker = Qwt.QWT.QwtPlotMarker()
|
|
||||||
ishorizontal = (plotattributes[:seriestype] == :hline)
|
|
||||||
marker[:setLineStyle](ishorizontal ? 1 : 2)
|
|
||||||
marker[ishorizontal ? :setYValue : :setXValue](yi)
|
|
||||||
qcolor = Qwt.convertRGBToQColor(getColor(plotattributes[:linecolor]))
|
|
||||||
linestyle = plt.o.widget[:getLineStyle](string(plotattributes[:linestyle]))
|
|
||||||
marker[:setLinePen](Qwt.QT.QPen(qcolor, plotattributes[:linewidth], linestyle))
|
|
||||||
marker[:attach](plt.o.widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
# marker[:setValue](x, y)
|
|
||||||
# marker[:setLabel](Qwt.QWT.QwtText(val))
|
|
||||||
# marker[:attach](plt.o.widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function createQwtAnnotation(plt::Plot, x, y, val::PlotText)
|
|
||||||
marker = Qwt.QWT.QwtPlotMarker()
|
|
||||||
marker[:setValue](x, y)
|
|
||||||
qwttext = Qwt.QWT.QwtText(val.str)
|
|
||||||
qwttext[:setFont](Qwt.QT.QFont(val.font.family, val.font.pointsize))
|
|
||||||
qwttext[:setColor](Qwt.convertRGBToQColor(getColor(val.font.color)))
|
|
||||||
marker[:setLabel](qwttext)
|
|
||||||
marker[:attach](plt.o.widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function createQwtAnnotation(plt::Plot, x, y, val::AbstractString)
|
|
||||||
marker = Qwt.QWT.QwtPlotMarker()
|
|
||||||
marker[:setValue](x, y)
|
|
||||||
marker[:setLabel](Qwt.QWT.QwtText(val))
|
|
||||||
marker[:attach](plt.o.widget)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _add_annotations(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
|
||||||
for ann in anns
|
|
||||||
createQwtAnnotation(plt, ann...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# accessors for x/y data
|
|
||||||
|
|
||||||
function getxy(plt::Plot{QwtBackend}, i::Int)
|
|
||||||
series = plt.o.lines[i]
|
|
||||||
series.x, series.y
|
|
||||||
end
|
|
||||||
|
|
||||||
function setxy!(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
|
||||||
series = plt.o.lines[i]
|
|
||||||
series.x, series.y = xy
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------
|
|
||||||
|
|
||||||
# -------------------------------
|
|
||||||
|
|
||||||
# # create the underlying object (each backend will do this differently)
|
|
||||||
# function _create_subplot(subplt::Subplot{QwtBackend}, isbefore::Bool)
|
|
||||||
# isbefore && return false
|
|
||||||
# i = 0
|
|
||||||
# rows = Any[]
|
|
||||||
# row = Any[]
|
|
||||||
# for (i,(r,c)) in enumerate(subplt.layout)
|
|
||||||
# push!(row, subplt.plts[i].o)
|
|
||||||
# if c == ncols(subplt.layout, r)
|
|
||||||
# push!(rows, Qwt.hsplitter(row...))
|
|
||||||
# row = Any[]
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# # for rowcnt in subplt.layout.rowcounts
|
|
||||||
# # push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...))
|
|
||||||
# # i += rowcnt
|
|
||||||
# # end
|
|
||||||
# subplt.o = Qwt.vsplitter(rows...)
|
|
||||||
# # Qwt.resizewidget(subplt.o, getattr(subplt,1)[:size]...)
|
|
||||||
# # Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry
|
|
||||||
# true
|
|
||||||
# end
|
|
||||||
|
|
||||||
function _expand_limits(lims, plt::Plot{QwtBackend}, isx::Bool)
|
|
||||||
for series in plt.o.lines
|
|
||||||
_expand_limits(lims, isx ? series.x : series.y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function _remove_axis(plt::Plot{QwtBackend}, isx::Bool)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function Base.show(io::IO, ::MIME"image/png", plt::Plot{QwtBackend})
|
|
||||||
Qwt.refresh(plt.o)
|
|
||||||
Qwt.savepng(plt.o, "/tmp/dfskjdhfkh.png")
|
|
||||||
write(io, readall("/tmp/dfskjdhfkh.png"))
|
|
||||||
end
|
|
||||||
|
|
||||||
# function Base.show(io::IO, ::MIME"image/png", subplt::Subplot{QwtBackend})
|
|
||||||
# for plt in subplt.plts
|
|
||||||
# Qwt.refresh(plt.o)
|
|
||||||
# end
|
|
||||||
# Qwt.savepng(subplt.o, "/tmp/dfskjdhfkh.png")
|
|
||||||
# write(io, readall("/tmp/dfskjdhfkh.png"))
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
function Base.display(::PlotsDisplay, plt::Plot{QwtBackend})
|
|
||||||
Qwt.refresh(plt.o)
|
|
||||||
Qwt.showwidget(plt.o)
|
|
||||||
end
|
|
||||||
|
|
||||||
# function Base.display(::PlotsDisplay, subplt::Subplot{QwtBackend})
|
|
||||||
# for plt in subplt.plts
|
|
||||||
# Qwt.refresh(plt.o)
|
|
||||||
# end
|
|
||||||
# Qwt.showwidget(subplt.o)
|
|
||||||
# end
|
|
||||||
@ -1,272 +0,0 @@
|
|||||||
|
|
||||||
# https://github.com/nolta/Winston.jl
|
|
||||||
|
|
||||||
# credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation
|
|
||||||
|
|
||||||
supported_attrs(::WinstonBackend) = merge_with_base_supported([
|
|
||||||
:annotations,
|
|
||||||
:linecolor,
|
|
||||||
:fillrange,
|
|
||||||
:fillcolor,
|
|
||||||
:label,
|
|
||||||
:legend,
|
|
||||||
:seriescolor, :seriesalpha,
|
|
||||||
:linestyle,
|
|
||||||
:linewidth,
|
|
||||||
:markershape,
|
|
||||||
:markercolor,
|
|
||||||
:markersize,
|
|
||||||
:bins,
|
|
||||||
:title,
|
|
||||||
:window_title,
|
|
||||||
:guide, :lims, :scale,
|
|
||||||
])
|
|
||||||
supported_types(::WinstonBackend) = [:path, :scatter, :bar]
|
|
||||||
supported_styles(::WinstonBackend) = [:auto, :solid, :dash, :dot, :dashdot]
|
|
||||||
supported_markers(::WinstonBackend) = [:none, :auto, :rect, :circle, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5]
|
|
||||||
supported_scales(::WinstonBackend) = [:identity, :log10]
|
|
||||||
is_subplot_supported(::WinstonBackend) = false
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function _initialize_backend(::WinstonBackend; kw...)
|
|
||||||
@eval begin
|
|
||||||
# ENV["WINSTON_OUTPUT"] = "gtk"
|
|
||||||
@warn("Winston is no longer supported... many features will likely be broken.")
|
|
||||||
import Winston, Gtk
|
|
||||||
export Winston, Gtk
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
## dictionaries for conversion of Plots.jl names to Winston ones.
|
|
||||||
const winston_linestyle = KW(:solid=>"solid",
|
|
||||||
:dash=>"dash",
|
|
||||||
:dot=>"dotted",
|
|
||||||
:dashdot=>"dotdashed"
|
|
||||||
)
|
|
||||||
|
|
||||||
const winston_marker = KW(:none=>".",
|
|
||||||
:rect => "square",
|
|
||||||
:circle=>"circle",
|
|
||||||
:diamond=>"diamond",
|
|
||||||
:utriangle=>"triangle",
|
|
||||||
:dtriangle=>"down-triangle",
|
|
||||||
:cross => "plus",
|
|
||||||
:xcross => "cross",
|
|
||||||
:star5 => "asterisk"
|
|
||||||
)
|
|
||||||
|
|
||||||
function _before_update(plt::Plot{WinstonBackend})
|
|
||||||
Winston.ghf(plt.o)
|
|
||||||
end
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function _create_backend_figure(plt::Plot{WinstonBackend})
|
|
||||||
Winston.FramedPlot(
|
|
||||||
title = plt.attr[:title],
|
|
||||||
xlabel = plt.attr[:xguide],
|
|
||||||
ylabel = plt.attr[:yguide]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
copy_remove(plotattributes::KW, s::Symbol) = delete!(copy(plotattributes), s)
|
|
||||||
|
|
||||||
function addRegressionLineWinston(plotattributes::KW, wplt)
|
|
||||||
xs, ys = regressionXY(plotattributes[:x], plotattributes[:y])
|
|
||||||
Winston.add(wplt, Winston.Curve(xs, ys, kind="dotted"))
|
|
||||||
end
|
|
||||||
|
|
||||||
function getWinstonItems(plt::Plot)
|
|
||||||
if isa(plt.o, Winston.FramedPlot)
|
|
||||||
wplt = plt.o
|
|
||||||
window, canvas = nothing, nothing
|
|
||||||
else
|
|
||||||
window, canvas, wplt = plt.o
|
|
||||||
end
|
|
||||||
window, canvas, wplt
|
|
||||||
end
|
|
||||||
|
|
||||||
function _series_added(plt::Plot{WinstonBackend}, series::Series)
|
|
||||||
plotattributes = series.plotattributes
|
|
||||||
window, canvas, wplt = getWinstonItems(plt)
|
|
||||||
|
|
||||||
# until we call it normally, do the hack
|
|
||||||
if plotattributes[:seriestype] == :bar
|
|
||||||
plotattributes = barHack(;plotattributes...)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
e = KW()
|
|
||||||
e[:color] = getColor(plotattributes[:linecolor])
|
|
||||||
e[:linewidth] = plotattributes[:linewidth]
|
|
||||||
e[:kind] = winston_linestyle[plotattributes[:linestyle]]
|
|
||||||
e[:symbolkind] = winston_marker[plotattributes[:markershape]]
|
|
||||||
# markercolor # same choices as `color`, or :match will set the color to be the same as `color`
|
|
||||||
e[:symbolsize] = plotattributes[:markersize] / 5
|
|
||||||
|
|
||||||
# pos # (Int,Int), move the enclosing window to this position
|
|
||||||
# screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## lintype :path, :step, :stepinverted, :sticks, :dots, :none, :histogram2d, :hexbin, :histogram, :bar
|
|
||||||
if plotattributes[:seriestype] == :none
|
|
||||||
Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor])))
|
|
||||||
|
|
||||||
elseif plotattributes[:seriestype] == :path
|
|
||||||
x, y = plotattributes[:x], plotattributes[:y]
|
|
||||||
Winston.add(wplt, Winston.Curve(x, y; e...))
|
|
||||||
|
|
||||||
fillrange = plotattributes[:fillrange]
|
|
||||||
if fillrange != nothing
|
|
||||||
if isa(fillrange, AbstractVector)
|
|
||||||
y2 = fillrange
|
|
||||||
else
|
|
||||||
y2 = Float64[fillrange for yi in y]
|
|
||||||
end
|
|
||||||
Winston.add(wplt, Winston.FillBetween(x, y, x, y2, fillcolor=getColor(plotattributes[:fillcolor])))
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif plotattributes[:seriestype] == :scatter
|
|
||||||
if plotattributes[:markershape] == :none
|
|
||||||
plotattributes[:markershape] = :circle
|
|
||||||
end
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :step
|
|
||||||
# fn = Winston.XXX
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :stepinverted
|
|
||||||
# fn = Winston.XXX
|
|
||||||
|
|
||||||
elseif plotattributes[:seriestype] == :sticks
|
|
||||||
Winston.add(wplt, Winston.Stems(plotattributes[:x], plotattributes[:y]; e...))
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :dots
|
|
||||||
# fn = Winston.XXX
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :histogram2d
|
|
||||||
# fn = Winston.XXX
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :hexbin
|
|
||||||
# fn = Winston.XXX
|
|
||||||
|
|
||||||
elseif plotattributes[:seriestype] == :histogram
|
|
||||||
hst = hist(plotattributes[:y], plotattributes[:bins])
|
|
||||||
Winston.add(wplt, Winston.Histogram(hst...; copy_remove(e, :bins)...))
|
|
||||||
|
|
||||||
# elseif plotattributes[:seriestype] == :bar
|
|
||||||
# # fn = Winston.XXX
|
|
||||||
|
|
||||||
else
|
|
||||||
error("seriestype $(plotattributes[:seriestype]) not supported by Winston.")
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# markershape
|
|
||||||
if plotattributes[:markershape] != :none
|
|
||||||
Winston.add(wplt, Winston.Points(plotattributes[:x], plotattributes[:y]; copy_remove(e, :kind)..., color=getColor(plotattributes[:markercolor])))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# optionally add a regression line
|
|
||||||
plotattributes[:smooth] && plotattributes[:seriestype] != :histogram && addRegressionLineWinston(plotattributes, wplt)
|
|
||||||
|
|
||||||
# push!(plt.seriesargs, plotattributes)
|
|
||||||
# plt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
const _winstonNames = KW(
|
|
||||||
:xlims => :xrange,
|
|
||||||
:ylims => :yrange,
|
|
||||||
:xscale => :xlog,
|
|
||||||
:yscale => :ylog,
|
|
||||||
)
|
|
||||||
|
|
||||||
function _update_plot_object(plt::Plot{WinstonBackend}, plotattributes::KW)
|
|
||||||
window, canvas, wplt = getWinstonItems(plt)
|
|
||||||
for k in (:xguide, :yguide, :title, :xlims, :ylims)
|
|
||||||
if haskey(plotattributes, k)
|
|
||||||
Winston.setattr(wplt, string(get(_winstonNames, k, k)), plotattributes[k])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k in (:xscale, :yscale)
|
|
||||||
if haskey(plotattributes, k)
|
|
||||||
islogscale = plotattributes[k] == :log10
|
|
||||||
Winston.setattr(wplt, (k == :xscale ? :xlog : :ylog), islogscale)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function createWinstonAnnotationObject(plt::Plot{WinstonBackend}, x, y, val::AbstractString)
|
|
||||||
Winston.text(x, y, val)
|
|
||||||
end
|
|
||||||
|
|
||||||
function _add_annotations(plt::Plot{WinstonBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
|
||||||
for ann in anns
|
|
||||||
createWinstonAnnotationObject(plt, ann...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
# function _create_subplot(subplt::Subplot{WinstonBackend}, isbefore::Bool)
|
|
||||||
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
|
|
||||||
# end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
|
||||||
|
|
||||||
function addWinstonLegend(plt::Plot, wplt)
|
|
||||||
if plt.attr[:legend] != :none
|
|
||||||
Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Base.show(io::IO, ::MIME"image/png", plt::AbstractPlot{WinstonBackend})
|
|
||||||
window, canvas, wplt = getWinstonItems(plt)
|
|
||||||
addWinstonLegend(plt, wplt)
|
|
||||||
show(io, "image/png", wplt)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Base.display(::PlotsDisplay, plt::Plot{WinstonBackend})
|
|
||||||
|
|
||||||
window, canvas, wplt = getWinstonItems(plt)
|
|
||||||
|
|
||||||
if window == nothing
|
|
||||||
if Winston.output_surface != :gtk
|
|
||||||
error("Gtk is the only supported display for Winston in Plots. Set `output_surface = gtk` in src/Winston.ini")
|
|
||||||
end
|
|
||||||
# initialize window
|
|
||||||
w,h = plt.attr[:size]
|
|
||||||
canvas = Gtk.GtkCanvasLeaf()
|
|
||||||
window = Gtk.GtkWindowLeaf(canvas, plt.attr[:window_title], w, h)
|
|
||||||
plt.o = (window, canvas, wplt)
|
|
||||||
end
|
|
||||||
|
|
||||||
addWinstonLegend(plt, wplt)
|
|
||||||
|
|
||||||
Winston.display(canvas, wplt)
|
|
||||||
Gtk.showall(window)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# function Base.display(::PlotsDisplay, subplt::Subplot{WinstonBackend})
|
|
||||||
# # TODO: display/show the Subplot object
|
|
||||||
# end
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,415 +0,0 @@
|
|||||||
|
|
||||||
abstract type ColorScheme end
|
|
||||||
|
|
||||||
Base.getindex(scheme::ColorScheme, i::Integer) = getColor(scheme, i)
|
|
||||||
|
|
||||||
export
|
|
||||||
cgrad
|
|
||||||
|
|
||||||
cgrad() = default_gradient()
|
|
||||||
|
|
||||||
function cgrad(arg, values = nothing; alpha = nothing, scale = :identity)
|
|
||||||
colors = ColorGradient(arg, alpha=alpha).colors
|
|
||||||
values = if values != nothing
|
|
||||||
values
|
|
||||||
elseif scale in (:log, :log10)
|
|
||||||
log10(range(1, stop=10, length=30))
|
|
||||||
elseif scale == :log2
|
|
||||||
log2(range(1, stop=2, length=30))
|
|
||||||
elseif scale == :ln
|
|
||||||
log(range(1, stop=pi, length=30))
|
|
||||||
elseif scale in (:exp, :exp10)
|
|
||||||
(exp10(range(0, stop=1, length=30)) - 1) / 9
|
|
||||||
else
|
|
||||||
range(0, stop=1, length=length(colors))
|
|
||||||
end
|
|
||||||
ColorGradient(colors, values)
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
getColor(scheme::ColorScheme) = getColor(scheme, 1)
|
|
||||||
getColorVector(scheme::ColorScheme) = [getColor(scheme)]
|
|
||||||
|
|
||||||
colorscheme(scheme::ColorScheme) = scheme
|
|
||||||
colorscheme(s::AbstractString; kw...) = colorscheme(Symbol(s); kw...)
|
|
||||||
colorscheme(s::Symbol; kw...) = haskey(_gradients, s) ? ColorGradient(s; kw...) : ColorWrapper(convertColor(s); kw...)
|
|
||||||
colorscheme(s::Symbol, vals::AVec{T}; kw...) where {T<:Real} = ColorGradient(s, vals; kw...)
|
|
||||||
colorscheme(cs::AVec, vs::AVec; kw...) = ColorGradient(cs, vs; kw...)
|
|
||||||
colorscheme(cs::AVec{T}; kw...) where {T<:Colorant} = ColorGradient(cs; kw...)
|
|
||||||
colorscheme(f::Function; kw...) = ColorFunction(f; kw...)
|
|
||||||
colorscheme(v::AVec; kw...) = ColorVector(v; kw...)
|
|
||||||
colorscheme(m::AMat; kw...) = size(m,1) == 1 ? map(c->colorscheme(c; kw...), m) : [colorscheme(m[:,i]; kw...) for i in 1:size(m,2)]'
|
|
||||||
colorscheme(c::Colorant; kw...) = ColorWrapper(c; kw...)
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
convertColor(c::AbstractString) = parse(Colorant, c)
|
|
||||||
convertColor(c::Symbol) = parse(Colorant, string(c))
|
|
||||||
convertColor(c::Colorant) = c
|
|
||||||
convertColor(cvec::AbstractVector) = map(convertColor, cvec)
|
|
||||||
convertColor(c::ColorScheme) = c
|
|
||||||
convertColor(v::Nothing) = RGBA(0,0,0,0)
|
|
||||||
convertColor(b::Bool) = b ? RGBA(0,0,0,1) : RGBA(0,0,0,0)
|
|
||||||
|
|
||||||
function convertColor(c, α::Real)
|
|
||||||
c = convertColor(c)
|
|
||||||
RGBA(RGB(getColor(c)), α)
|
|
||||||
end
|
|
||||||
convertColor(cs::AVec, α::Real) = map(c -> convertColor(c, α), cs)
|
|
||||||
convertColor(c, α::Nothing) = convertColor(c)
|
|
||||||
|
|
||||||
# backup... try to convert
|
|
||||||
getColor(c) = convertColor(c)
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
function darken(c, v=0.1)
|
|
||||||
rgba = convert(RGBA, c)
|
|
||||||
r = max(0, min(rgba.r - v, 1))
|
|
||||||
g = max(0, min(rgba.g - v, 1))
|
|
||||||
b = max(0, min(rgba.b - v, 1))
|
|
||||||
RGBA(r,g,b,rgba.alpha)
|
|
||||||
end
|
|
||||||
function lighten(c, v=0.3)
|
|
||||||
darken(c, -v)
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
const _rainbowColors = [colorant"purple", colorant"blue", colorant"green", colorant"orange", colorant"red"]
|
|
||||||
const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcyan",colorant"green",
|
|
||||||
darken(colorant"yellow",0.3), colorant"orange", darken(colorant"red",0.2)]
|
|
||||||
|
|
||||||
const _gradients = KW(
|
|
||||||
:blues => [colorant"lightblue", colorant"darkblue"],
|
|
||||||
:reds => [colorant"lightpink", colorant"darkred"],
|
|
||||||
:greens => [colorant"lightgreen", colorant"darkgreen"],
|
|
||||||
:redsblues => [colorant"darkred", RGB(0.8,0.85,0.8), colorant"darkblue"],
|
|
||||||
:bluesreds => [colorant"darkblue", RGB(0.8,0.85,0.8), colorant"darkred"],
|
|
||||||
:heat => [colorant"lightyellow", colorant"orange", colorant"darkred"],
|
|
||||||
:grays => [RGB(.95,.95,.95),RGB(.05,.05,.05)],
|
|
||||||
:rainbow => _rainbowColors,
|
|
||||||
:lightrainbow => map(lighten, _rainbowColors),
|
|
||||||
:darkrainbow => map(darken, _rainbowColors),
|
|
||||||
:darktest => _testColors,
|
|
||||||
:lighttest => map(c -> lighten(c, 0.3), _testColors),
|
|
||||||
)
|
|
||||||
|
|
||||||
function register_gradient_colors(name::Symbol, colors::AVec{C}) where C<:Colorant
|
|
||||||
_gradients[name] = colors
|
|
||||||
end
|
|
||||||
|
|
||||||
include("color_gradients.jl")
|
|
||||||
|
|
||||||
default_gradient() = ColorGradient(:inferno)
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
|
|
||||||
struct ColorGradient <: ColorScheme
|
|
||||||
colors::Vector
|
|
||||||
values::Vector
|
|
||||||
|
|
||||||
function ColorGradient(cs::AVec, vals::AVec{S} = range(0, stop=1, length=length(cs)); alpha = nothing) where S<:Real
|
|
||||||
if length(cs) == length(vals)
|
|
||||||
return new(convertColor(cs,alpha), collect(vals))
|
|
||||||
end
|
|
||||||
|
|
||||||
# # otherwise interpolate evenly between the minval and maxval
|
|
||||||
# minval, maxval = minimum(vals), maximum(vals)
|
|
||||||
# vs = Float64[interpolate(minval, maxval, w) for w in range(0, stop = 1, length = length(cs))]
|
|
||||||
# new(convertColor(cs,alpha), vs)
|
|
||||||
|
|
||||||
# interpolate the colors for each value
|
|
||||||
vals = merge(range(0, stop=1, length=length(cs)), vals)
|
|
||||||
grad = ColorGradient(cs)
|
|
||||||
cs = [getColorZ(grad, z) for z in range(0, stop=1, length=length(vals))]
|
|
||||||
new(convertColor(cs, alpha), vals)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Base.getindex(cs::ColorGradient, i::Integer) = getColor(cs, i)
|
|
||||||
Base.getindex(cs::ColorGradient, z::Number) = getColorZ(cs, z)
|
|
||||||
|
|
||||||
|
|
||||||
# create a gradient from a symbol (blues, reds, etc) and vector of boundary values
|
|
||||||
function ColorGradient(s::Symbol, vals::AVec{T} = 0:0; kw...) where T<:Real
|
|
||||||
haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients))))
|
|
||||||
cs = _gradients[s]
|
|
||||||
if vals == 0:0
|
|
||||||
vals = range(0, stop=1, length=length(cs))
|
|
||||||
end
|
|
||||||
ColorGradient(cs, vals; kw...)
|
|
||||||
end
|
|
||||||
|
|
||||||
# function ColorGradient{T<:Real}(cs::AVec, vals::AVec{T} = range(0, stop = 1, length = length(cs)); kw...)
|
|
||||||
# ColorGradient(map(convertColor, cs), vals; kw...)
|
|
||||||
# end
|
|
||||||
|
|
||||||
function ColorGradient(grad::ColorGradient; alpha = nothing)
|
|
||||||
ColorGradient(convertColor(grad.colors, alpha), grad.values)
|
|
||||||
end
|
|
||||||
|
|
||||||
# anything else just gets the default gradient
|
|
||||||
function ColorGradient(cw; alpha=nothing)
|
|
||||||
ColorGradient(default_gradient(), alpha=alpha)
|
|
||||||
end
|
|
||||||
|
|
||||||
getColor(gradient::ColorGradient, idx::Int) = gradient.colors[mod1(idx, length(gradient.colors))]
|
|
||||||
|
|
||||||
function getColorZ(gradient::ColorGradient, z::Real)
|
|
||||||
cs = gradient.colors
|
|
||||||
vs = gradient.values
|
|
||||||
n = length(cs)
|
|
||||||
@assert n > 0 && n == length(vs)
|
|
||||||
|
|
||||||
# can we just return the first color?
|
|
||||||
if z <= vs[1] || n == 1
|
|
||||||
return cs[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
# find the bounding colors and interpolate
|
|
||||||
for i in 2:n
|
|
||||||
if z <= vs[i]
|
|
||||||
return interpolate_rgb(cs[i-1], cs[i], (z - vs[i-1]) / (vs[i] - vs[i-1]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# if we get here, return the last color
|
|
||||||
cs[end]
|
|
||||||
end
|
|
||||||
|
|
||||||
getColorVector(gradient::ColorGradient) = gradient.colors
|
|
||||||
|
|
||||||
# for 0.3
|
|
||||||
Colors.RGBA(c::Colorant) = RGBA(red(c), green(c), blue(c), alpha(c))
|
|
||||||
Colors.RGB(c::Colorant) = RGB(red(c), green(c), blue(c))
|
|
||||||
|
|
||||||
function interpolate_rgb(c1::Colorant, c2::Colorant, w::Real)
|
|
||||||
rgb1 = RGBA(c1)
|
|
||||||
rgb2 = RGBA(c2)
|
|
||||||
r = interpolate(rgb1.r, rgb2.r, w)
|
|
||||||
g = interpolate(rgb1.g, rgb2.g, w)
|
|
||||||
b = interpolate(rgb1.b, rgb2.b, w)
|
|
||||||
a = interpolate(rgb1.alpha, rgb2.alpha, w)
|
|
||||||
RGBA(r, g, b, a)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function interpolate(v1::Real, v2::Real, w::Real)
|
|
||||||
(1-w) * v1 + w * v2
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
"Wraps a function, taking an index and returning a Colorant"
|
|
||||||
struct ColorFunction <: ColorScheme
|
|
||||||
f::Function
|
|
||||||
end
|
|
||||||
|
|
||||||
getColor(scheme::ColorFunction, idx::Int) = scheme.f(idx)
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
"Wraps a function, taking an z-value and returning a Colorant"
|
|
||||||
struct ColorZFunction <: ColorScheme
|
|
||||||
f::Function
|
|
||||||
end
|
|
||||||
|
|
||||||
getColorZ(scheme::ColorZFunction, z::Real) = scheme.f(z)
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
"Wraps a vector of colors... may be vector of Symbol/String/Colorant"
|
|
||||||
struct ColorVector <: ColorScheme
|
|
||||||
v::Vector{Colorant}
|
|
||||||
ColorVector(v::AVec; alpha = nothing) = new(convertColor(v,alpha))
|
|
||||||
end
|
|
||||||
|
|
||||||
getColor(scheme::ColorVector, idx::Int) = convertColor(scheme.v[mod1(idx, length(scheme.v))])
|
|
||||||
getColorVector(scheme::ColorVector) = scheme.v
|
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
"Wraps a single color"
|
|
||||||
struct ColorWrapper <: ColorScheme
|
|
||||||
c::RGBA
|
|
||||||
ColorWrapper(c::Colorant; alpha = nothing) = new(convertColor(c, alpha))
|
|
||||||
end
|
|
||||||
|
|
||||||
ColorWrapper(s::Symbol; alpha = nothing) = ColorWrapper(convertColor(parse(Colorant, s), alpha))
|
|
||||||
|
|
||||||
getColor(scheme::ColorWrapper, idx::Int) = scheme.c
|
|
||||||
getColorZ(scheme::ColorWrapper, z::Real) = scheme.c
|
|
||||||
convertColor(c::ColorWrapper, α::Nothing) = c.c
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
isbackgrounddark(bgcolor::Color) = Lab(bgcolor).l < 0.5
|
|
||||||
|
|
||||||
# move closer to lighter/darker depending on background value
|
|
||||||
function adjustAway(val, bgval, vmin=0., vmax=100.)
|
|
||||||
if bgval < 0.5 * (vmax+vmin)
|
|
||||||
tmp = max(val, bgval)
|
|
||||||
return 0.5 * (tmp + max(tmp, vmax))
|
|
||||||
else
|
|
||||||
tmp = min(val, bgval)
|
|
||||||
return 0.5 * (tmp + min(tmp, vmin))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# borrowed from http://stackoverflow.com/a/1855903:
|
|
||||||
lightnessLevel(c::Colorant) = 0.299 * red(c) + 0.587 * green(c) + 0.114 * blue(c)
|
|
||||||
|
|
||||||
isdark(c::Colorant) = lightnessLevel(c) < 0.5
|
|
||||||
islight(c::Colorant) = !isdark(c)
|
|
||||||
|
|
||||||
function convertHexToRGB(h::Unsigned)
|
|
||||||
mask = 0x0000FF
|
|
||||||
RGB([(x & mask) / 0xFF for x in (h >> 16, h >> 8, h)]...)
|
|
||||||
end
|
|
||||||
|
|
||||||
# note: I found this list of hex values in a comment by Tatarize here: http://stackoverflow.com/a/12224359
|
|
||||||
const _masterColorList = [
|
|
||||||
0xFFFFFF, 0x000000, 0x0000FF, 0x00FF00, 0xFF0000, 0x01FFFE, 0xFFA6FE, 0xFFDB66, 0x006401, 0x010067,
|
|
||||||
0x95003A, 0x007DB5, 0xFF00F6, 0xFFEEE8, 0x774D00, 0x90FB92, 0x0076FF, 0xD5FF00, 0xFF937E, 0x6A826C,
|
|
||||||
0xFF029D, 0xFE8900, 0x7A4782, 0x7E2DD2, 0x85A900, 0xFF0056, 0xA42400, 0x00AE7E, 0x683D3B, 0xBDC6FF,
|
|
||||||
0x263400, 0xBDD393, 0x00B917, 0x9E008E, 0x001544, 0xC28C9F, 0xFF74A3, 0x01D0FF, 0x004754, 0xE56FFE,
|
|
||||||
0x788231, 0x0E4CA1, 0x91D0CB, 0xBE9970, 0x968AE8, 0xBB8800, 0x43002C, 0xDEFF74, 0x00FFC6, 0xFFE502,
|
|
||||||
0x620E00, 0x008F9C, 0x98FF52, 0x7544B1, 0xB500FF, 0x00FF78, 0xFF6E41, 0x005F39, 0x6B6882, 0x5FAD4E,
|
|
||||||
0xA75740, 0xA5FFD2, 0xFFB167, 0x009BFF, 0xE85EBE
|
|
||||||
]
|
|
||||||
const _allColors = map(convertHexToRGB, _masterColorList)
|
|
||||||
const _darkColors = filter(isdark, _allColors)
|
|
||||||
const _lightColors = filter(islight, _allColors)
|
|
||||||
const _sortedColorsForDarkBackground = vcat(_lightColors, reverse(_darkColors[2:end]))
|
|
||||||
const _sortedColorsForLightBackground = vcat(_darkColors, reverse(_lightColors[2:end]))
|
|
||||||
|
|
||||||
const _defaultNumColors = 17
|
|
||||||
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
|
|
||||||
# Methods to automatically generate gradients for color selection based on
|
|
||||||
# background color and a short list of seed colors
|
|
||||||
|
|
||||||
# here are some magic constants that could be changed if you really want
|
|
||||||
const _lightness_darkbg = [80.0]
|
|
||||||
const _lightness_lightbg = [60.0]
|
|
||||||
const _lch_c_const = [60]
|
|
||||||
|
|
||||||
function adjust_lch(color, l, c)
|
|
||||||
lch = convert(LCHab, color)
|
|
||||||
convert(RGB, LCHab(l, c, lch.h))
|
|
||||||
end
|
|
||||||
|
|
||||||
function lightness_from_background(bgcolor)
|
|
||||||
bglight = convert(LCHab, bgcolor).l
|
|
||||||
bglight < 50.0 ? _lightness_darkbg[1] : _lightness_lightbg[1]
|
|
||||||
end
|
|
||||||
|
|
||||||
function gradient_from_list(cs)
|
|
||||||
zvalues = Plots.get_zvalues(length(cs))
|
|
||||||
indices = sortperm(zvalues)
|
|
||||||
sorted_colors = map(RGBA, cs[indices])
|
|
||||||
sorted_zvalues = zvalues[indices]
|
|
||||||
ColorGradient(sorted_colors, sorted_zvalues)
|
|
||||||
end
|
|
||||||
|
|
||||||
function generate_colorgradient(bgcolor = colorant"white";
|
|
||||||
color_bases = color_bases=[colorant"steelblue",colorant"orangered"],
|
|
||||||
lightness = lightness_from_background(bgcolor),
|
|
||||||
chroma = _lch_c_const[1],
|
|
||||||
n = _defaultNumColors)
|
|
||||||
seed_colors = vcat(bgcolor, map(c -> adjust_lch(c, lightness, chroma), color_bases))
|
|
||||||
colors = distinguishable_colors(n,
|
|
||||||
seed_colors,
|
|
||||||
lchoices=Float64[lightness],
|
|
||||||
cchoices=Float64[chroma],
|
|
||||||
hchoices=range(0, stop=340, length=20)
|
|
||||||
)[2:end]
|
|
||||||
gradient_from_list(colors)
|
|
||||||
end
|
|
||||||
|
|
||||||
function get_color_palette(palette, bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer)
|
|
||||||
grad = if palette == :auto
|
|
||||||
generate_colorgradient(bgcolor)
|
|
||||||
else
|
|
||||||
ColorGradient(palette)
|
|
||||||
end
|
|
||||||
zrng = get_zvalues(numcolors)
|
|
||||||
RGBA[getColorZ(grad, z) for z in zrng]
|
|
||||||
end
|
|
||||||
|
|
||||||
function get_color_palette(palette::Vector{C},
|
|
||||||
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) where C<:Colorant
|
|
||||||
palette
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
function getpctrange(n::Int)
|
|
||||||
n > 0 || error()
|
|
||||||
n == 1 && return zeros(1)
|
|
||||||
zs = [0.0, 1.0]
|
|
||||||
for i in 3:n
|
|
||||||
sorted = sort(zs)
|
|
||||||
diffs = diff(sorted)
|
|
||||||
widestj = 0
|
|
||||||
widest = 0.0
|
|
||||||
for (j,d) in enumerate(diffs)
|
|
||||||
if d > widest
|
|
||||||
widest = d
|
|
||||||
widestj = j
|
|
||||||
end
|
|
||||||
end
|
|
||||||
push!(zs, sorted[widestj] + 0.5 * diffs[widestj])
|
|
||||||
end
|
|
||||||
zs
|
|
||||||
end
|
|
||||||
|
|
||||||
function get_zvalues(n::Int)
|
|
||||||
offsets = getpctrange(ceil(Int,n/4)+1)/4
|
|
||||||
offsets = vcat(offsets[1], offsets[3:end])
|
|
||||||
zvalues = Float64[]
|
|
||||||
for offset in offsets
|
|
||||||
append!(zvalues, offset + [0.0, 0.5, 0.25, 0.75])
|
|
||||||
end
|
|
||||||
vcat(zvalues[1], 1.0, zvalues[2:n-1])
|
|
||||||
end
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
make255(x) = round(Int, 255 * x)
|
|
||||||
|
|
||||||
function webcolor(c::Color)
|
|
||||||
@sprintf("rgb(%d, %d, %d)", [make255(f(c)) for f in [red,green,blue]]...)
|
|
||||||
end
|
|
||||||
function webcolor(c::TransparentColor)
|
|
||||||
@sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
|
|
||||||
end
|
|
||||||
webcolor(cs::ColorScheme) = webcolor(getColor(cs))
|
|
||||||
webcolor(c) = webcolor(convertColor(c))
|
|
||||||
webcolor(c, α) = webcolor(convertColor(getColor(c), α))
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
|
|
||||||
function getSeriesRGBColor(c, sp::Subplot, n::Int)
|
|
||||||
|
|
||||||
if c == :auto
|
|
||||||
c = autopick(sp[:color_palette], n)
|
|
||||||
end
|
|
||||||
|
|
||||||
# c should now be a subtype of ColorScheme
|
|
||||||
colorscheme(c)
|
|
||||||
end
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
"""
|
|
||||||
- load Contours.jl similar to DataFrames
|
|
||||||
- method to build grid from x/y/z vectors
|
|
||||||
- method to wrap contours creation
|
|
||||||
- method to plot contours as custom shapes (TODO: create Stroke and Fill types and add markerstroke/markerfill args)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# # ----------------------------------------------------------
|
|
||||||
# # ----------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# immutable Vertex
|
|
||||||
# x::Float64
|
|
||||||
# y::Float64
|
|
||||||
# z::Float64
|
|
||||||
# end
|
|
||||||
|
|
||||||
# immutable Edge
|
|
||||||
# v::Vertex
|
|
||||||
# u::Vertex
|
|
||||||
# end
|
|
||||||
|
|
||||||
# # ----------------------------------------------------------
|
|
||||||
|
|
||||||
# # one rectangle's z-values and the center vertex
|
|
||||||
# # z is ordered: topleft, topright, bottomright, bottomleft
|
|
||||||
# immutable GridRect
|
|
||||||
# z::Vector{Float64}
|
|
||||||
# center::Vertex
|
|
||||||
# data::Vector{Vertex}
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# type Grid
|
|
||||||
# xs::Vector{Float64}
|
|
||||||
# ys::Vector{Float64}
|
|
||||||
# rects::Matrix{GridRect}
|
|
||||||
# end
|
|
||||||
|
|
||||||
# function splitDataEvenly(v::AbstractVector{Float64}, n::Int)
|
|
||||||
# vs = sort(v)
|
|
||||||
|
|
||||||
# end
|
|
||||||
|
|
||||||
# # the goal here is to create the vertical and horizontal partitions
|
|
||||||
# # which define the grid, so that the data is somewhat evenly split
|
|
||||||
# function bucketData(x, y, z)
|
|
||||||
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
# function buildGrid(x, y, z)
|
|
||||||
# # create
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
|
|
||||||
# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems].
|
|
||||||
# Special handling for: no args, xmin/xmax, parametric, dataframes
|
|
||||||
# Then once inputs have been converted, build the series args, map functions, etc.
|
|
||||||
# This should cut down on boilerplate code and allow more focused dispatch on type
|
|
||||||
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
|
|
||||||
|
|
||||||
const FuncOrFuncs = Union{Function, AVec{Function}}
|
|
||||||
|
|
||||||
all3D(plotattributes::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(plotattributes, :seriestype, :none))
|
|
||||||
|
|
||||||
# missing
|
|
||||||
convertToAnyVector(v::Nothing, plotattributes::KW) = Any[nothing], nothing
|
|
||||||
|
|
||||||
# fixed number of blank series
|
|
||||||
convertToAnyVector(n::Integer, plotattributes::KW) = Any[zeros(0) for i in 1:n], nothing
|
|
||||||
|
|
||||||
# numeric vector
|
|
||||||
convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:Number} = Any[v], nothing
|
|
||||||
|
|
||||||
# string vector
|
|
||||||
convertToAnyVector(v::AVec{T}, plotattributes::KW) where {T<:AbstractString} = Any[v], nothing
|
|
||||||
|
|
||||||
function convertToAnyVector(v::AMat, plotattributes::KW)
|
|
||||||
if all3D(plotattributes)
|
|
||||||
Any[Surface(v)]
|
|
||||||
else
|
|
||||||
Any[v[:,i] for i in 1:size(v,2)]
|
|
||||||
end, nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
# function
|
|
||||||
convertToAnyVector(f::Function, plotattributes::KW) = Any[f], nothing
|
|
||||||
|
|
||||||
# surface
|
|
||||||
convertToAnyVector(s::Surface, plotattributes::KW) = Any[s], nothing
|
|
||||||
|
|
||||||
# # vector of OHLC
|
|
||||||
# convertToAnyVector(v::AVec{OHLC}, plotattributes::KW) = Any[v], nothing
|
|
||||||
|
|
||||||
# dates
|
|
||||||
convertToAnyVector(dts::AVec{D}, plotattributes::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
|
|
||||||
|
|
||||||
# list of things (maybe other vectors, functions, or something else)
|
|
||||||
function convertToAnyVector(v::AVec, plotattributes::KW)
|
|
||||||
if all(x -> typeof(x) <: Number, v)
|
|
||||||
# all real numbers wrap the whole vector as one item
|
|
||||||
Any[convert(Vector{Float64}, v)], nothing
|
|
||||||
else
|
|
||||||
# something else... treat each element as an item
|
|
||||||
vcat(Any[convertToAnyVector(vi, plotattributes)[1] for vi in v]...), nothing
|
|
||||||
# Any[vi for vi in v], nothing
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
convertToAnyVector(t::Tuple, plotattributes::KW) = Any[t], nothing
|
|
||||||
|
|
||||||
|
|
||||||
function convertToAnyVector(args...)
|
|
||||||
error("In convertToAnyVector, could not handle the argument types: $(map(typeof, args[1:end-1]))")
|
|
||||||
end
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
|
|
||||||
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
|
|
||||||
# result in that array being shared. push!, etc will add too many items to that array
|
|
||||||
|
|
||||||
compute_x(x::Nothing, y::Nothing, z) = 1:size(z,1)
|
|
||||||
compute_x(x::Nothing, y, z) = 1:size(y,1)
|
|
||||||
compute_x(x::Function, y, z) = map(x, y)
|
|
||||||
compute_x(x, y, z) = copy(x)
|
|
||||||
|
|
||||||
# compute_y(x::Void, y::Function, z) = error()
|
|
||||||
compute_y(x::Nothing, y::Nothing, z) = 1:size(z,2)
|
|
||||||
compute_y(x, y::Function, z) = map(y, x)
|
|
||||||
compute_y(x, y, z) = copy(y)
|
|
||||||
|
|
||||||
compute_z(x, y, z::Function) = map(z, x, y)
|
|
||||||
compute_z(x, y, z::AbstractMatrix) = Surface(z)
|
|
||||||
compute_z(x, y, z::Nothing) = nothing
|
|
||||||
compute_z(x, y, z) = copy(z)
|
|
||||||
|
|
||||||
nobigs(v::AVec{BigFloat}) = map(Float64, v)
|
|
||||||
nobigs(v::AVec{BigInt}) = map(Int64, v)
|
|
||||||
nobigs(v) = v
|
|
||||||
|
|
||||||
@noinline function compute_xyz(x, y, z)
|
|
||||||
x = compute_x(x,y,z)
|
|
||||||
y = compute_y(x,y,z)
|
|
||||||
z = compute_z(x,y,z)
|
|
||||||
nobigs(x), nobigs(y), nobigs(z)
|
|
||||||
end
|
|
||||||
|
|
||||||
# not allowed
|
|
||||||
compute_xyz(x::Nothing, y::FuncOrFuncs, z) = error("If you want to plot the function `$y`, you need to define the x values!")
|
|
||||||
compute_xyz(x::Nothing, y::Nothing, z::FuncOrFuncs) = error("If you want to plot the function `$z`, you need to define x and y values!")
|
|
||||||
compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all nothing!")
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
|
||||||
@ -435,8 +435,37 @@ each line segment or marker in the plot.
|
|||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
|
PlotExample("Portfolio Composition maps",
|
||||||
|
"""
|
||||||
|
see: http://stackoverflow.com/a/37732384/5075246
|
||||||
|
""",
|
||||||
|
[:(begin
|
||||||
|
using Random
|
||||||
|
Random.seed!(111)
|
||||||
|
tickers = ["IBM", "Google", "Apple", "Intel"]
|
||||||
|
N = 10
|
||||||
|
D = length(tickers)
|
||||||
|
weights = rand(N,D)
|
||||||
|
weights ./= sum(weights, dims = 2)
|
||||||
|
returns = sort!((1:N) + D*randn(N))
|
||||||
|
|
||||||
|
portfoliocomposition(weights, returns, labels = permutedims(tickers))
|
||||||
|
end)]
|
||||||
|
),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Some constants for PlotDocs and PlotReferenceImages
|
||||||
|
_animation_examples = [2, 30]
|
||||||
|
_backend_skips = Dict(
|
||||||
|
:gr => [25, 30],
|
||||||
|
:pyplot => [25, 30],
|
||||||
|
:plotlyjs => [2, 21, 25, 30, 31],
|
||||||
|
:pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
# make and display one plot
|
# make and display one plot
|
||||||
@ -473,7 +502,7 @@ function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = noth
|
|||||||
plts[i] = plt
|
plts[i] = plt
|
||||||
catch ex
|
catch ex
|
||||||
# TODO: put error info into markdown?
|
# TODO: put error info into markdown?
|
||||||
warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
|
@warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex")
|
||||||
end
|
end
|
||||||
if sleep != nothing
|
if sleep != nothing
|
||||||
Base.sleep(sleep)
|
Base.sleep(sleep)
|
||||||
|
|||||||
56
src/init.jl
56
src/init.jl
@ -1,4 +1,9 @@
|
|||||||
|
using REPL
|
||||||
|
|
||||||
|
const use_local_dependencies = Ref(false)
|
||||||
|
|
||||||
function __init__()
|
function __init__()
|
||||||
|
|
||||||
if isdefined(Main, :PLOTS_DEFAULTS)
|
if isdefined(Main, :PLOTS_DEFAULTS)
|
||||||
if haskey(Main.PLOTS_DEFAULTS, :theme)
|
if haskey(Main.PLOTS_DEFAULTS, :theme)
|
||||||
theme(Main.PLOTS_DEFAULTS[:theme])
|
theme(Main.PLOTS_DEFAULTS[:theme])
|
||||||
@ -7,20 +12,16 @@ function __init__()
|
|||||||
k == :theme || default(k, v)
|
k == :theme || default(k, v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
pushdisplay(PlotsDisplay())
|
|
||||||
|
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
|
||||||
|
|
||||||
atreplinit(i -> begin
|
atreplinit(i -> begin
|
||||||
if PlotDisplay() in Base.Multimedia.displays
|
while PlotsDisplay() in Base.Multimedia.displays
|
||||||
popdisplay(PlotsDisplay())
|
popdisplay(PlotsDisplay())
|
||||||
end
|
end
|
||||||
pushdisplay(PlotsDisplay())
|
insert!(Base.Multimedia.displays, findlast(x -> x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
|
||||||
end)
|
end)
|
||||||
|
|
||||||
include(joinpath(@__DIR__, "backends", "plotly.jl"))
|
|
||||||
include(joinpath(@__DIR__, "backends", "gr.jl"))
|
|
||||||
include(joinpath(@__DIR__, "backends", "web.jl"))
|
|
||||||
|
|
||||||
@require GLVisualize = "4086de5b-f4b6-55f3-abb0-b8c73827585f" include(joinpath(@__DIR__, "backends", "glvisualize.jl"))
|
|
||||||
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl"))
|
@require HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" include(joinpath(@__DIR__, "backends", "hdf5.jl"))
|
||||||
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" include(joinpath(@__DIR__, "backends", "inspectdr.jl"))
|
@require InspectDR = "d0351b0e-4b05-5898-87b3-e2a8edfddd1d" include(joinpath(@__DIR__, "backends", "inspectdr.jl"))
|
||||||
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" include(joinpath(@__DIR__, "backends", "pgfplots.jl"))
|
@require PGFPlots = "3b7a836e-365b-5785-a47d-02c71176b4aa" include(joinpath(@__DIR__, "backends", "pgfplots.jl"))
|
||||||
@ -31,10 +32,11 @@ function __init__()
|
|||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
# IJulia
|
# IJulia
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
use_local = false
|
||||||
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
|
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
|
||||||
if IJulia.inited
|
if IJulia.inited
|
||||||
|
# IJulia is more stable with local file
|
||||||
|
use_local = isfile(plotly_local_file_path)
|
||||||
"""
|
"""
|
||||||
Add extra jupyter mimetypes to display_dict based on the plot backed.
|
Add extra jupyter mimetypes to display_dict based on the plot backed.
|
||||||
|
|
||||||
@ -84,4 +86,38 @@ function __init__()
|
|||||||
ENV["MPLBACKEND"] = "Agg"
|
ENV["MPLBACKEND"] = "Agg"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL")
|
||||||
|
use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
|
||||||
|
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local
|
||||||
|
if use_local && !isfile(plotly_local_file_path)
|
||||||
|
@warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
use_local_dependencies[] = use_local
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------
|
||||||
|
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
|
||||||
|
@require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin
|
||||||
|
PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
|
||||||
|
function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
|
||||||
|
fn = tempname()
|
||||||
|
|
||||||
|
# first save a pdf file
|
||||||
|
pdf(plt, fn)
|
||||||
|
|
||||||
|
# load that pdf into a FileIO Stream
|
||||||
|
s = FileIO.load(fn * ".pdf")
|
||||||
|
|
||||||
|
# save a png
|
||||||
|
pngfn = fn * ".png"
|
||||||
|
FileIO.save(pngfn, s)
|
||||||
|
|
||||||
|
# now write from the file
|
||||||
|
write(io, read(open(pngfn), String))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -156,7 +156,6 @@ end
|
|||||||
const _best_html_output_type = KW(
|
const _best_html_output_type = KW(
|
||||||
:pyplot => :png,
|
:pyplot => :png,
|
||||||
:unicodeplots => :txt,
|
:unicodeplots => :txt,
|
||||||
:glvisualize => :png,
|
|
||||||
:plotlyjs => :html,
|
:plotlyjs => :html,
|
||||||
:plotly => :html
|
:plotly => :html
|
||||||
)
|
)
|
||||||
@ -210,30 +209,6 @@ _show(io::IO, ::MIME{Symbol("text/plain")}, plt::Plot) = show(io, plt)
|
|||||||
closeall() = closeall(backend())
|
closeall() = closeall(backend())
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
|
|
||||||
|
|
||||||
const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
|
|
||||||
if is_installed("FileIO")
|
|
||||||
@eval import FileIO
|
|
||||||
function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
|
|
||||||
fn = tempname()
|
|
||||||
|
|
||||||
# first save a pdf file
|
|
||||||
pdf(plt, fn)
|
|
||||||
|
|
||||||
# load that pdf into a FileIO Stream
|
|
||||||
s = FileIO.load(fn * ".pdf")
|
|
||||||
|
|
||||||
# save a png
|
|
||||||
pngfn = fn * ".png"
|
|
||||||
FileIO.save(pngfn, s)
|
|
||||||
|
|
||||||
# now write from the file
|
|
||||||
write(io, read(open(pngfn), String))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# function html_output_format(fmt)
|
# function html_output_format(fmt)
|
||||||
# if fmt == "png"
|
# if fmt == "png"
|
||||||
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
|
# @eval function Base.show(io::IO, ::MIME"text/html", plt::Plot)
|
||||||
@ -267,9 +242,21 @@ function showjuno(io::IO, m, plt)
|
|||||||
plt[:thickness_scaling] *= scale
|
plt[:thickness_scaling] *= scale
|
||||||
|
|
||||||
prepare_output(plt)
|
prepare_output(plt)
|
||||||
_show(io, m, plt)
|
try
|
||||||
|
_showjuno(io, m, plt)
|
||||||
plt[:size] = sz
|
finally
|
||||||
plt[:dpi] = dpi
|
plt[:size] = sz
|
||||||
plt[:thickness_scaling] = thickness_scaling
|
plt[:dpi] = dpi
|
||||||
|
plt[:thickness_scaling] = thickness_scaling
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function _showjuno(io::IO, m::MIME"image/svg+xml", plt)
|
||||||
|
if Symbol(plt.attr[:html_output_format]) ≠ :svg
|
||||||
|
throw(MethodError(show, (typeof(m), typeof(plt))))
|
||||||
|
else
|
||||||
|
_show(io, m, plt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_showjuno(io::IO, m, plt) = _show(io, m, plt)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ end
|
|||||||
plotattr([attr])
|
plotattr([attr])
|
||||||
|
|
||||||
Look up the properties of a Plots attribute, or specify an attribute type. Call `plotattr()` for options.
|
Look up the properties of a Plots attribute, or specify an attribute type. Call `plotattr()` for options.
|
||||||
The information is the same as that given on https://juliaplots.github.io/attributes/.
|
The information is the same as that given on https://docs.juliaplots.org/latest/attributes/.
|
||||||
"""
|
"""
|
||||||
function plotattr()
|
function plotattr()
|
||||||
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
|
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
|
||||||
|
|||||||
@ -1131,3 +1131,25 @@ end
|
|||||||
title := string(grad.args[1])
|
title := string(grad.args[1])
|
||||||
z
|
z
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Moved in from PlotRecipes - see: http://stackoverflow.com/a/37732384/5075246
|
||||||
|
@userplot PortfolioComposition
|
||||||
|
|
||||||
|
# this shows the shifting composition of a basket of something over a variable
|
||||||
|
# - "returns" are the dependent variable
|
||||||
|
# - "weights" are a matrix where the ith column is the composition for returns[i]
|
||||||
|
# - since each polygon is its own series, you can assign labels easily
|
||||||
|
@recipe function f(pc::PortfolioComposition)
|
||||||
|
weights, returns = pc.args
|
||||||
|
n = length(returns)
|
||||||
|
weights = cumsum(weights, dims = 2)
|
||||||
|
seriestype := :shape
|
||||||
|
|
||||||
|
# create a filled polygon for each item
|
||||||
|
for c=1:size(weights,2)
|
||||||
|
sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1]))
|
||||||
|
sy = vcat(returns, reverse(returns))
|
||||||
|
@series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@ -386,8 +386,9 @@ end
|
|||||||
xmin, xmax = try
|
xmin, xmax = try
|
||||||
axis_limits(plt[1][:xaxis])
|
axis_limits(plt[1][:xaxis])
|
||||||
catch
|
catch
|
||||||
xm = tryrange(f, [-5,-1,0,0.01])
|
xinv = invscalefunc(get(plotattributes, :xscale, :identity))
|
||||||
xm, tryrange(f, filter(x->x>xm, [5,1,0.99, 0, -0.01]))
|
xm = tryrange(f, xinv.([-5,-1,0,0.01]))
|
||||||
|
xm, tryrange(f, filter(x->x>xm, xinv.([5,1,0.99, 0, -0.01])))
|
||||||
end
|
end
|
||||||
|
|
||||||
f, xmin, xmax
|
f, xmin, xmax
|
||||||
@ -517,16 +518,23 @@ end
|
|||||||
#
|
#
|
||||||
# # special handling... xmin/xmax with parametric function(s)
|
# # special handling... xmin/xmax with parametric function(s)
|
||||||
@recipe function f(f::Function, xmin::Number, xmax::Number)
|
@recipe function f(f::Function, xmin::Number, xmax::Number)
|
||||||
xs = adapted_grid(f, (xmin, xmax))
|
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
|
||||||
|
xs = _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
|
||||||
xs, f
|
xs, f
|
||||||
end
|
end
|
||||||
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
|
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
|
||||||
xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs]
|
xscale, yscale = [get(plotattributes, sym, :identity) for sym=(:xscale,:yscale)]
|
||||||
|
xs = Any[_scaled_adapted_grid(f, xscale, yscale, xmin, xmax) for f in fs]
|
||||||
xs, fs
|
xs, fs
|
||||||
end
|
end
|
||||||
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
|
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
|
||||||
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = fx, fy, range(umin, stop = umax, length = n)
|
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = fx, fy, range(umin, stop = umax, length = n)
|
||||||
|
|
||||||
|
function _scaled_adapted_grid(f, xscale, yscale, xmin, xmax)
|
||||||
|
(xf, xinv), (yf, yinv) = ((scalefunc(s),invscalefunc(s)) for s in (xscale,yscale))
|
||||||
|
xinv.(adapted_grid(yf∘f∘xinv, xf.((xmin, xmax))))
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# # special handling... 3D parametric function(s)
|
# # special handling... 3D parametric function(s)
|
||||||
@recipe function f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec) where {F<:Function,G<:Function,H<:Function}
|
@recipe function f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec) where {F<:Function,G<:Function,H<:Function}
|
||||||
@ -539,7 +547,7 @@ end
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# # --------------------------------------------------------------------
|
# # --------------------------------------------------------------------
|
||||||
# # Lists of tuples and FixedSizeArrays
|
# # Lists of tuples and StaticArrays
|
||||||
# # --------------------------------------------------------------------
|
# # --------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# # if we get an unhandled tuple, just splat it in
|
# # if we get an unhandled tuple, just splat it in
|
||||||
@ -561,14 +569,14 @@ end
|
|||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# # 2D FixedSizeArrays
|
# # 2D StaticArrays
|
||||||
@recipe f(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T<:Number} = unzip(xy)
|
@recipe f(xy::AVec{StaticArrays.SVector{2,T}}) where {T<:Number} = unzip(xy)
|
||||||
@recipe f(xy::FixedSizeArrays.Vec{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
|
@recipe f(xy::StaticArrays.SVector{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
|
||||||
|
|
||||||
#
|
#
|
||||||
# # 3D FixedSizeArrays
|
# # 3D StaticArrays
|
||||||
@recipe f(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T<:Number} = unzip(xyz)
|
@recipe f(xyz::AVec{StaticArrays.SVector{3,T}}) where {T<:Number} = unzip(xyz)
|
||||||
@recipe f(xyz::FixedSizeArrays.Vec{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
|
@recipe f(xyz::StaticArrays.SVector{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
|
||||||
|
|
||||||
#
|
#
|
||||||
# # --------------------------------------------------------------------
|
# # --------------------------------------------------------------------
|
||||||
|
|||||||
23
src/utils.jl
23
src/utils.jl
@ -287,14 +287,14 @@ unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2]
|
|||||||
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
|
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
|
||||||
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
|
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
|
||||||
|
|
||||||
unzip(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
|
unzip(xy::AVec{StaticArrays.SVector{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
|
||||||
unzip(xy::FixedSizeArrays.Vec{2,T}) where {T} = T[xy[1]], T[xy[2]]
|
unzip(xy::StaticArrays.SVector{2,T}) where {T} = T[xy[1]], T[xy[2]]
|
||||||
|
|
||||||
unzip(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
|
unzip(xyz::AVec{StaticArrays.SVector{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
|
||||||
unzip(xyz::FixedSizeArrays.Vec{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
|
unzip(xyz::StaticArrays.SVector{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
|
||||||
|
|
||||||
unzip(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
|
unzip(xyuv::AVec{StaticArrays.SVector{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
|
||||||
unzip(xyuv::FixedSizeArrays.Vec{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
|
unzip(xyuv::StaticArrays.SVector{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
|
||||||
|
|
||||||
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
||||||
function _expand_limits(lims, x)
|
function _expand_limits(lims, x)
|
||||||
@ -357,6 +357,7 @@ const _scale_base = Dict{Symbol, Real}(
|
|||||||
)
|
)
|
||||||
|
|
||||||
function _heatmap_edges(v::AVec)
|
function _heatmap_edges(v::AVec)
|
||||||
|
length(v) == 1 && return v[1] .+ [-0.5, 0.5]
|
||||||
vmin, vmax = ignorenan_extrema(v)
|
vmin, vmax = ignorenan_extrema(v)
|
||||||
extra_min = (v[2] - v[1]) / 2
|
extra_min = (v[2] - v[1]) / 2
|
||||||
extra_max = (v[end] - v[end - 1]) / 2
|
extra_max = (v[end] - v[end - 1]) / 2
|
||||||
@ -412,14 +413,6 @@ end
|
|||||||
isijulia() = :IJulia in nameof.(collect(values(Base.loaded_modules)))
|
isijulia() = :IJulia in nameof.(collect(values(Base.loaded_modules)))
|
||||||
isatom() = :Atom in nameof.(collect(values(Base.loaded_modules)))
|
isatom() = :Atom in nameof.(collect(values(Base.loaded_modules)))
|
||||||
|
|
||||||
function is_installed(pkgstr::AbstractString)
|
|
||||||
try
|
|
||||||
Pkg.installed(pkgstr) === nothing ? false : true
|
|
||||||
catch
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
istuple(::Tuple) = true
|
istuple(::Tuple) = true
|
||||||
istuple(::Any) = false
|
istuple(::Any) = false
|
||||||
isvector(::AVec) = true
|
isvector(::AVec) = true
|
||||||
@ -745,7 +738,7 @@ function with(f::Function, args...; kw...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# # TODO: generalize this strategy to allow args as much as possible
|
# # TODO: generalize this strategy to allow args as much as possible
|
||||||
# # as in: with(:gadfly, :scatter, :legend, :grid) do; ...; end
|
# # as in: with(:gr, :scatter, :legend, :grid) do; ...; end
|
||||||
# # TODO: can we generalize this enough to also do something similar in the plot commands??
|
# # TODO: can we generalize this enough to also do something similar in the plot commands??
|
||||||
|
|
||||||
# k = :seriestype
|
# k = :seriestype
|
||||||
|
|||||||
@ -4,7 +4,6 @@ using Pkg
|
|||||||
# ENV["PYTHON"] = ""
|
# ENV["PYTHON"] = ""
|
||||||
|
|
||||||
to_add = [
|
to_add = [
|
||||||
PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"),
|
|
||||||
# PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"),
|
# PackageSpec(url="https://github.com/JuliaStats/KernelDensity.jl.git"),
|
||||||
PackageSpec(name="PlotUtils", rev="master"),
|
PackageSpec(name="PlotUtils", rev="master"),
|
||||||
PackageSpec(name="RecipesBase", rev="master"),
|
PackageSpec(name="RecipesBase", rev="master"),
|
||||||
@ -17,12 +16,24 @@ to_add = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
if isinteractive()
|
if isinteractive()
|
||||||
|
Pkg.develop(PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"))
|
||||||
append!(to_add, [
|
append!(to_add, [
|
||||||
PackageSpec(name="FileIO"),
|
PackageSpec(name="FileIO"),
|
||||||
PackageSpec(name="ImageMagick"),
|
PackageSpec(name="ImageMagick"),
|
||||||
PackageSpec(name="UnicodePlots"),
|
PackageSpec(name="UnicodePlots"),
|
||||||
PackageSpec(name="VisualRegressionTests"),
|
PackageSpec(name="VisualRegressionTests"),
|
||||||
|
PackageSpec(name="Gtk"),
|
||||||
|
# PlotlyJS:
|
||||||
|
# PackageSpec(name="PlotlyJS"),
|
||||||
|
# PackageSpec(name="Blink"),
|
||||||
|
# PackageSpec(name="ORCA"),
|
||||||
|
# PyPlot:
|
||||||
|
# PackageSpec(name="PyPlot"),
|
||||||
|
# PackageSpec(name="PyCall"),
|
||||||
|
# PackageSpec(name="LaTeXStrings"),
|
||||||
])
|
])
|
||||||
|
else
|
||||||
|
push!(to_add, PackageSpec(url="https://github.com/JuliaPlots/PlotReferenceImages.jl.git"))
|
||||||
end
|
end
|
||||||
|
|
||||||
Pkg.add(to_add)
|
Pkg.add(to_add)
|
||||||
|
|||||||
@ -29,7 +29,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
|
# 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)
|
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
|
||||||
|
|
||||||
const _current_plots_version = v"0.17.4"
|
import Plots._current_plots_version
|
||||||
|
|
||||||
|
|
||||||
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2)
|
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], tol = 1e-2)
|
||||||
|
|||||||
@ -14,16 +14,19 @@ img_tol = isinteractive() ? 1e-2 : 10e-2
|
|||||||
@test gr() == Plots.GRBackend()
|
@test gr() == Plots.GRBackend()
|
||||||
@test backend() == Plots.GRBackend()
|
@test backend() == Plots.GRBackend()
|
||||||
|
|
||||||
image_comparison_facts(:gr, tol=img_tol, skip = [25, 30])
|
@static if Sys.islinux()
|
||||||
|
image_comparison_facts(:gr, tol=img_tol, skip = [25, 30])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @static if isinteractive()
|
||||||
#@testset "PyPlot" begin
|
# @testset "PyPlot" begin
|
||||||
# @test pyplot() == Plots.PyPlotBackend()
|
# @test pyplot() == Plots.PyPlotBackend()
|
||||||
# @test backend() == Plots.PyPlotBackend()
|
# @test backend() == Plots.PyPlotBackend()
|
||||||
#
|
#
|
||||||
# image_comparison_facts(:pyplot, tol=img_tol)
|
# image_comparison_facts(:pyplot, tol=img_tol, skip = [2, 25, 30, 31])
|
||||||
#end
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
@testset "UnicodePlots" begin
|
@testset "UnicodePlots" begin
|
||||||
@test unicodeplots() == Plots.UnicodePlotsBackend()
|
@test unicodeplots() == Plots.UnicodePlotsBackend()
|
||||||
@ -36,22 +39,23 @@ end
|
|||||||
# The plotlyjs testimages return a connection error on travis:
|
# The plotlyjs testimages return a connection error on travis:
|
||||||
# connect: connection refused (ECONNREFUSED)
|
# connect: connection refused (ECONNREFUSED)
|
||||||
|
|
||||||
# @testset "PlotlyJS" begin
|
# @static if isinteractive()
|
||||||
# @test plotlyjs() == Plots.PlotlyJSBackend()
|
# @testset "PlotlyJS" begin
|
||||||
# @test backend() == Plots.PlotlyJSBackend()
|
# @test plotlyjs() == Plots.PlotlyJSBackend()
|
||||||
|
# @test backend() == Plots.PlotlyJSBackend()
|
||||||
#
|
#
|
||||||
# if Sys.islinux() && isinteractive()
|
|
||||||
# image_comparison_facts(:plotlyjs,
|
# image_comparison_facts(:plotlyjs,
|
||||||
# skip=[
|
# skip=[
|
||||||
# 2, # animation (skipped for speed)
|
# 2, # animation (skipped for speed)
|
||||||
|
# 25,
|
||||||
# 27, # (polar plots) takes very long / not working
|
# 27, # (polar plots) takes very long / not working
|
||||||
|
# 30,
|
||||||
# 31, # animation (skipped for speed)
|
# 31, # animation (skipped for speed)
|
||||||
# ],
|
# ],
|
||||||
# tol=img_tol)
|
# tol=img_tol)
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
|
||||||
# InspectDR returns that error on travis:
|
# InspectDR returns that error on travis:
|
||||||
# ERROR: LoadError: InitError: Cannot open display:
|
# ERROR: LoadError: InitError: Cannot open display:
|
||||||
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
|
# in Gtk.GLib.GError(::Gtk.##229#230) at /home/travis/.julia/v0.5/Gtk/src/GLib/gerror.jl:17
|
||||||
@ -83,16 +87,6 @@ end
|
|||||||
# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol)
|
# # @static Sys.islinux() && image_comparison_facts(:plotly, only=[1,3,4,7,8,9,10,11,12,14,15,20,22,23,27], tol=img_tol)
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
|
||||||
# @testset "Immerse" begin
|
|
||||||
# @test immerse() == Plots.ImmerseBackend()
|
|
||||||
# @test backend() == Plots.ImmerseBackend()
|
|
||||||
#
|
|
||||||
# # as long as we can plot anything without error, it should be the same as Gadfly
|
|
||||||
# image_comparison_facts(:immerse, only=[1], tol=img_tol)
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
# @testset "PlotlyJS" begin
|
# @testset "PlotlyJS" begin
|
||||||
# @test plotlyjs() == Plots.PlotlyJSBackend()
|
# @test plotlyjs() == Plots.PlotlyJSBackend()
|
||||||
# @test backend() == Plots.PlotlyJSBackend()
|
# @test backend() == Plots.PlotlyJSBackend()
|
||||||
@ -102,19 +96,6 @@ end
|
|||||||
# end
|
# end
|
||||||
|
|
||||||
|
|
||||||
# @testset "Gadfly" begin
|
|
||||||
# @test gadfly() == Plots.GadflyBackend()
|
|
||||||
# @test backend() == Plots.GadflyBackend()
|
|
||||||
#
|
|
||||||
# @test typeof(plot(1:10)) == Plots.Plot{Plots.GadflyBackend}
|
|
||||||
# @test plot(Int[1,2,3], rand(3)) == not(nothing)
|
|
||||||
# @test plot(sort(rand(10)), rand(Int, 10, 3)) == not(nothing)
|
|
||||||
# @test plot!(rand(10,3), rand(10,3)) == not(nothing)
|
|
||||||
#
|
|
||||||
# image_comparison_facts(:gadfly, skip=[4,6,23,24,27], tol=img_tol)
|
|
||||||
# end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@testset "Axes" begin
|
@testset "Axes" begin
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user