Merge 2b4f9f15ff7e9592b6d9163dc36e5e0e5a2472e5 into 25bf71aff229af4bd01d9fa4c94bc8d2bd0a3e6f
This commit is contained in:
commit
d360b12508
41
NEWS.md
41
NEWS.md
@ -3,14 +3,47 @@
|
|||||||
|
|
||||||
#### notes on release changes, ongoing development, and future planned work
|
#### notes on release changes, ongoing development, and future planned work
|
||||||
|
|
||||||
- All new development should target 0.9!
|
- All new development should target 0.12!
|
||||||
- Minor version 0.8 is the last one to support Julia 0.4!!
|
- Minor version 0.11 is the last one to support Julia 0.5!!
|
||||||
- Critical bugfixes only
|
- Critical bugfixes only
|
||||||
- `backports` branch is for Julia 0.4
|
- `backports` branch is for Julia 0.4
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 0.9 (current master/dev)
|
## 0.11 (current master/dev)
|
||||||
|
|
||||||
|
#### 0.11.0
|
||||||
|
|
||||||
|
- julia 0.6 compatibility
|
||||||
|
- matplotlib 0.2.0 compatibility
|
||||||
|
- add inspectdr backend
|
||||||
|
- improved histogram functionality:
|
||||||
|
- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default)
|
||||||
|
- support for log scale axes with histograms
|
||||||
|
- support for plotting `StatsBase.Histogram`
|
||||||
|
- allowing bins to be specified as `:sturges`, `:rice`, `:scott` or :fd
|
||||||
|
- allow `normalization` to be specified as :density (for unequal bins) or :pdf (sum to 1)
|
||||||
|
- add a `plotattr` function to access documentation for Plots attribute
|
||||||
|
- add `fill_z` attribute for pyplot
|
||||||
|
- add colorbar_title to plotlyjs
|
||||||
|
- enable standalone window for plotlyjs
|
||||||
|
- improved support for pgfplots, ticks rotation, clims, series_annotations
|
||||||
|
- restore colorbars for GR
|
||||||
|
- better axis labels for heatmap in GR
|
||||||
|
- better marker sizes in GR
|
||||||
|
- fix color representation in GR
|
||||||
|
- update GR legend
|
||||||
|
- fix image bug on GR
|
||||||
|
- fix glvisualize dependencies
|
||||||
|
- set dotted grid lines for pyplot
|
||||||
|
- several improvements to inspectdr
|
||||||
|
- improved tick positions for TimeType x axes
|
||||||
|
- support for improved color gradient capability in PlotUtils
|
||||||
|
- add a showlibrary recipe to display color libraries
|
||||||
|
- add a showgradient recipe to display color gradients
|
||||||
|
- add `vectorfield` as an alias for `quiver`
|
||||||
|
- use `PlotUtils.adaptedgrid` for functions
|
||||||
|
|
||||||
|
|
||||||
#### 0.9.5
|
#### 0.9.5
|
||||||
|
|
||||||
@ -331,7 +364,7 @@
|
|||||||
- z-axis keywords
|
- z-axis keywords
|
||||||
- 3D indexing overhaul: `push!`, `append!` support
|
- 3D indexing overhaul: `push!`, `append!` support
|
||||||
- matplotlib colormap constants (`:inferno` is the new default colormap for Plots)
|
- matplotlib colormap constants (`:inferno` is the new default colormap for Plots)
|
||||||
- `typealias KW Dict{Symbol,Any}` used in place of splatting in many places
|
- `const KW = Dict{Symbol,Any}` used in place of splatting in many places
|
||||||
- png generation for plotly backend using wkhtmltoimage
|
- png generation for plotly backend using wkhtmltoimage
|
||||||
- `normalize` and `weights` keywords
|
- `normalize` and `weights` keywords
|
||||||
- background/foreground subcategories for fine-tuning of looks
|
- background/foreground subcategories for fine-tuning of looks
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Plots
|
# Plots
|
||||||
|
|
||||||
[](https://travis-ci.org/tbreloff/Plots.jl)
|
[](https://travis-ci.org/JuliaPlots/Plots.jl)
|
||||||
[](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
|
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
|
||||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
|
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
|
||||||
|
|||||||
5
REQUIRE
5
REQUIRE
@ -1,9 +1,10 @@
|
|||||||
julia 0.5
|
julia 0.5
|
||||||
|
|
||||||
RecipesBase
|
RecipesBase
|
||||||
PlotUtils
|
PlotUtils 0.4.1
|
||||||
PlotThemes
|
PlotThemes 0.1.3
|
||||||
Reexport
|
Reexport
|
||||||
Measures
|
Measures
|
||||||
Showoff
|
Showoff
|
||||||
|
StatsBase 0.14.0
|
||||||
StaticArrays
|
StaticArrays
|
||||||
|
|||||||
11
src/Plots.jl
11
src/Plots.jl
@ -9,6 +9,7 @@ using Base.Meta
|
|||||||
@reexport using PlotUtils
|
@reexport using PlotUtils
|
||||||
@reexport using PlotThemes
|
@reexport using PlotThemes
|
||||||
import Showoff
|
import Showoff
|
||||||
|
import StatsBase
|
||||||
|
|
||||||
export
|
export
|
||||||
grid,
|
grid,
|
||||||
@ -99,13 +100,15 @@ export
|
|||||||
center,
|
center,
|
||||||
P2,
|
P2,
|
||||||
P3,
|
P3,
|
||||||
BezierCurve
|
BezierCurve,
|
||||||
|
|
||||||
|
plotattr
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
import Measures
|
import Measures
|
||||||
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
|
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
|
||||||
typealias BBox Measures.Absolute2DBox
|
const BBox = Measures.Absolute2DBox
|
||||||
export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
|
export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
@ -127,6 +130,7 @@ include("animation.jl")
|
|||||||
include("output.jl")
|
include("output.jl")
|
||||||
include("examples.jl")
|
include("examples.jl")
|
||||||
include("arg_desc.jl")
|
include("arg_desc.jl")
|
||||||
|
include("plotattr.jl")
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
@ -145,6 +149,9 @@ end
|
|||||||
@shorthands bar
|
@shorthands bar
|
||||||
@shorthands barh
|
@shorthands barh
|
||||||
@shorthands histogram
|
@shorthands histogram
|
||||||
|
@shorthands barhist
|
||||||
|
@shorthands stephist
|
||||||
|
@shorthands scatterhist
|
||||||
@shorthands histogram2d
|
@shorthands histogram2d
|
||||||
@shorthands density
|
@shorthands density
|
||||||
@shorthands heatmap
|
@shorthands heatmap
|
||||||
|
|||||||
@ -80,7 +80,8 @@ function buildanimation(animdir::AbstractString, fn::AbstractString;
|
|||||||
|
|
||||||
catch err
|
catch err
|
||||||
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
|
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
|
||||||
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
|
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`.
|
||||||
|
You may also need to install the imagemagick c++ library through your operating system.
|
||||||
Will try ffmpeg, but it's lower quality...)""")
|
Will try ffmpeg, but it's lower quality...)""")
|
||||||
|
|
||||||
# low quality
|
# low quality
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const _arg_desc = KW(
|
|||||||
:markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)",
|
:markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)",
|
||||||
:markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.",
|
:markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.",
|
||||||
:markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.",
|
:markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.",
|
||||||
:bins => "Integer, NTuple{2,Integer}, AbstractVector. For histogram-types, defines the number of bins, or the edges, of the histogram.",
|
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)",
|
||||||
:smooth => "Bool. Add a regression line?",
|
:smooth => "Bool. Add a regression line?",
|
||||||
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
|
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
|
||||||
:x => "Various. Input data. First Dimension",
|
:x => "Various. Input data. First Dimension",
|
||||||
@ -40,7 +40,7 @@ const _arg_desc = KW(
|
|||||||
:ribbon => "Number or AbstractVector. Creates a fillrange around the data points.",
|
:ribbon => "Number or AbstractVector. Creates a fillrange around the data points.",
|
||||||
:quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.",
|
:quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.",
|
||||||
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
|
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
|
||||||
:normalize => "Bool. Should normalize histogram types? Trying for area == 1.",
|
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a PDF with integral of 1) and :density (only normalize in respect to bin sizes).",
|
||||||
:weights => "AbstractVector. Used in histogram types for weighted counts.",
|
:weights => "AbstractVector. Used in histogram types for weighted counts.",
|
||||||
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
|
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
|
||||||
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
|
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
|
||||||
|
|||||||
15
src/args.jl
15
src/args.jl
@ -35,7 +35,9 @@ const _3dTypes = [
|
|||||||
]
|
]
|
||||||
const _allTypes = vcat([
|
const _allTypes = vcat([
|
||||||
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
||||||
:heatmap, :hexbin, :histogram, :histogram2d, :histogram3d, :density, :bar, :hline, :vline,
|
:heatmap, :hexbin, :barbins, :barhist, :histogram, :scatterbins,
|
||||||
|
:scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :histogram3d,
|
||||||
|
:density, :bar, :hline, :vline,
|
||||||
:contour, :pie, :shape, :image
|
:contour, :pie, :shape, :image
|
||||||
], _3dTypes)
|
], _3dTypes)
|
||||||
|
|
||||||
@ -65,6 +67,7 @@ const _typeAliases = Dict{Symbol,Symbol}(
|
|||||||
:polygon => :shape,
|
:polygon => :shape,
|
||||||
:box => :boxplot,
|
:box => :boxplot,
|
||||||
:velocity => :quiver,
|
:velocity => :quiver,
|
||||||
|
:vectorfield => :quiver,
|
||||||
:gradient => :quiver,
|
:gradient => :quiver,
|
||||||
:img => :image,
|
:img => :image,
|
||||||
:imshow => :image,
|
:imshow => :image,
|
||||||
@ -77,7 +80,7 @@ const _typeAliases = Dict{Symbol,Symbol}(
|
|||||||
|
|
||||||
add_non_underscore_aliases!(_typeAliases)
|
add_non_underscore_aliases!(_typeAliases)
|
||||||
|
|
||||||
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :density)
|
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins)
|
||||||
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
|
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
|
||||||
like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image)
|
like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image)
|
||||||
|
|
||||||
@ -153,6 +156,8 @@ const _markerAliases = Dict{Symbol,Symbol}(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
|
const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
|
||||||
|
const _logScales = [:ln, :log2, :log10]
|
||||||
|
const _logScaleBases = Dict(:ln => e, :log2 => 2.0, :log10 => 10.0)
|
||||||
const _scaleAliases = Dict{Symbol,Symbol}(
|
const _scaleAliases = Dict{Symbol,Symbol}(
|
||||||
:none => :identity,
|
:none => :identity,
|
||||||
:log => :log10,
|
:log => :log10,
|
||||||
@ -180,7 +185,7 @@ const _series_defaults = KW(
|
|||||||
:markerstrokewidth => 1,
|
:markerstrokewidth => 1,
|
||||||
:markerstrokecolor => :match,
|
:markerstrokecolor => :match,
|
||||||
:markerstrokealpha => nothing,
|
:markerstrokealpha => nothing,
|
||||||
:bins => 30, # number of bins for hists
|
:bins => :auto, # number of bins for hists
|
||||||
:smooth => false, # regression line?
|
:smooth => false, # regression line?
|
||||||
:group => nothing, # groupby vector
|
:group => nothing, # groupby vector
|
||||||
:x => nothing,
|
:x => nothing,
|
||||||
@ -445,7 +450,7 @@ add_aliases(:color_palette, :palette)
|
|||||||
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
|
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
|
||||||
add_aliases(:xerror, :xerr, :xerrorbar)
|
add_aliases(:xerror, :xerr, :xerrorbar)
|
||||||
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
|
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
|
||||||
add_aliases(:quiver, :velocity, :quiver2d, :gradient)
|
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
|
||||||
add_aliases(:normalize, :norm, :normed, :normalized)
|
add_aliases(:normalize, :norm, :normed, :normalized)
|
||||||
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
|
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
|
||||||
add_aliases(:match_dimensions, :transpose, :transpose_z)
|
add_aliases(:match_dimensions, :transpose, :transpose_z)
|
||||||
@ -1260,7 +1265,7 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# scatter plots don't have a line, but must have a shape
|
# scatter plots don't have a line, but must have a shape
|
||||||
if d[:seriestype] in (:scatter, :scatter3d)
|
if d[:seriestype] in (:scatter, :scatterbins, :scatterhist, :scatter3d)
|
||||||
d[:linewidth] = 0
|
d[:linewidth] = 0
|
||||||
if d[:markershape] == :none
|
if d[:markershape] == :none
|
||||||
d[:markershape] = :circle
|
d[:markershape] = :circle
|
||||||
|
|||||||
26
src/axes.jl
26
src/axes.jl
@ -156,6 +156,30 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
|
|||||||
scale = axis[:scale]
|
scale = axis[:scale]
|
||||||
sf = scalefunc(scale)
|
sf = scalefunc(scale)
|
||||||
|
|
||||||
|
# If the axis input was a Date or DateTime use a special logic to find
|
||||||
|
# "round" Date(Time)s as ticks
|
||||||
|
# This bypasses the rest of optimal_ticks_and_labels, because
|
||||||
|
# optimize_datetime_ticks returns ticks AND labels: the label format (Date
|
||||||
|
# or DateTime) is chosen based on the time span between amin and amax
|
||||||
|
# rather than on the input format
|
||||||
|
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
|
||||||
|
if ticks == nothing && scale == :identity
|
||||||
|
if axis[:formatter] == dateformatter
|
||||||
|
# optimize_datetime_ticks returns ticks and labels(!) based on
|
||||||
|
# integers/floats corresponding to the DateTime type. Thus, the axes
|
||||||
|
# limits, which resulted from converting the Date type to integers,
|
||||||
|
# are converted to 'DateTime integers' (actually floats) before
|
||||||
|
# being passed to optimize_datetime_ticks.
|
||||||
|
# (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i)
|
||||||
|
ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax;
|
||||||
|
k_min = 2, k_max = 4)
|
||||||
|
# Now the ticks are converted back to floats corresponding to Dates.
|
||||||
|
return ticks / 864e5, labels
|
||||||
|
elseif axis[:formatter] == datetimeformatter
|
||||||
|
return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# get a list of well-laid-out ticks
|
# get a list of well-laid-out ticks
|
||||||
scaled_ticks = if ticks == nothing
|
scaled_ticks = if ticks == nothing
|
||||||
optimize_ticks(
|
optimize_ticks(
|
||||||
@ -214,7 +238,7 @@ function get_ticks(axis::Axis)
|
|||||||
# @show ticks dvals cv dv
|
# @show ticks dvals cv dv
|
||||||
|
|
||||||
# TODO: better/smarter cutoff values for sampling ticks
|
# TODO: better/smarter cutoff values for sampling ticks
|
||||||
if length(cv) > 30
|
if length(cv) > 30 && ticks == :auto
|
||||||
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
||||||
cv[rng], dv[rng]
|
cv[rng], dv[rng]
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
``#=
|
#=
|
||||||
TODO
|
TODO
|
||||||
* move all gl_ methods to GLPlot
|
* move all gl_ methods to GLPlot
|
||||||
* integrate GLPlot UI
|
* integrate GLPlot UI
|
||||||
@ -7,7 +7,6 @@ TODO
|
|||||||
* polar plots
|
* polar plots
|
||||||
* labes and axis
|
* labes and axis
|
||||||
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
|
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
|
||||||
* why is there so little unicode supported in the font!??!?
|
|
||||||
=#
|
=#
|
||||||
|
|
||||||
const _glvisualize_attr = merge_with_base_supported([
|
const _glvisualize_attr = merge_with_base_supported([
|
||||||
@ -134,11 +133,6 @@ function empty_screen!(screen)
|
|||||||
end
|
end
|
||||||
nothing
|
nothing
|
||||||
end
|
end
|
||||||
function poll_reactive()
|
|
||||||
# run_till_now blocks when message queue is empty!
|
|
||||||
Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function get_plot_screen(list::Vector, name, result = [])
|
function get_plot_screen(list::Vector, name, result = [])
|
||||||
for elem in list
|
for elem in list
|
||||||
@ -155,19 +149,20 @@ function get_plot_screen(screen, name, result = [])
|
|||||||
end
|
end
|
||||||
|
|
||||||
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
||||||
name = Symbol("Plots.jl")
|
name = Symbol("__Plots.jl")
|
||||||
# make sure we have any screen open
|
# make sure we have any screen open
|
||||||
if isempty(GLVisualize.get_screens())
|
if isempty(GLVisualize.get_screens())
|
||||||
# create a fresh, new screen
|
# create a fresh, new screen
|
||||||
parent_screen = GLVisualize.glscreen(
|
parent_screen = GLVisualize.glscreen(
|
||||||
"Plot",
|
"Plots",
|
||||||
resolution = plt[:size],
|
resolution = plt[:size],
|
||||||
visible = visible
|
visible = visible
|
||||||
)
|
)
|
||||||
@async GLWindow.waiting_renderloop(parent_screen)
|
@async GLWindow.waiting_renderloop(parent_screen)
|
||||||
|
GLVisualize.add_screen(parent_screen)
|
||||||
end
|
end
|
||||||
# now lets get ourselves a permanent Plotting screen
|
# now lets get ourselves a permanent Plotting screen
|
||||||
plot_screens = get_plot_screen(GLVisualize.get_screens(), name)
|
plot_screens = get_plot_screen(GLVisualize.current_screen(), name)
|
||||||
screen = if isempty(plot_screens) # no screen with `name`
|
screen = if isempty(plot_screens) # no screen with `name`
|
||||||
parent = GLVisualize.current_screen()
|
parent = GLVisualize.current_screen()
|
||||||
screen = GLWindow.Screen(
|
screen = GLWindow.Screen(
|
||||||
@ -183,7 +178,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
|||||||
else
|
else
|
||||||
# okay this is silly! Lets see if we can. There is an ID we could use
|
# okay this is silly! Lets see if we can. There is an ID we could use
|
||||||
# will not be fine for more than 255 screens though -.-.
|
# will not be fine for more than 255 screens though -.-.
|
||||||
error("multiple Plot screens. Please don't use any screen with the name Plots.jl")
|
error("multiple Plot screens. Please don't use any screen with the name $name")
|
||||||
end
|
end
|
||||||
# Since we own this window, we can do deep cleansing
|
# Since we own this window, we can do deep cleansing
|
||||||
empty_screen!(screen)
|
empty_screen!(screen)
|
||||||
@ -1141,8 +1136,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
|
|||||||
vis = gl_bar(d, kw_args)
|
vis = gl_bar(d, kw_args)
|
||||||
elseif st == :image
|
elseif st == :image
|
||||||
extract_extrema(d, kw_args)
|
extract_extrema(d, kw_args)
|
||||||
z = transpose_z(series, d[:z].surf, false)
|
vis = GL.gl_image(d[:z].surf, kw_args)
|
||||||
vis = GL.gl_image(z, kw_args)
|
|
||||||
elseif st == :boxplot
|
elseif st == :boxplot
|
||||||
extract_c(d, kw_args, :fill)
|
extract_c(d, kw_args, :fill)
|
||||||
vis = gl_boxplot(d, kw_args)
|
vis = gl_boxplot(d, kw_args)
|
||||||
@ -1182,7 +1176,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
|
|||||||
if _3d
|
if _3d
|
||||||
GLAbstraction.center!(sp_screen)
|
GLAbstraction.center!(sp_screen)
|
||||||
end
|
end
|
||||||
Reactive.post_empty()
|
GLAbstraction.post_empty()
|
||||||
yield()
|
yield()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1422,6 +1416,8 @@ function label_scatter(d, w, ho)
|
|||||||
color = get(kw, :color, nothing)
|
color = get(kw, :color, nothing)
|
||||||
kw[:color] = isa(color, Array) ? first(color) : color
|
kw[:color] = isa(color, Array) ? first(color) : color
|
||||||
end
|
end
|
||||||
|
strcolor = get(kw, :stroke_color, RGBA{Float32}(0,0,0,0))
|
||||||
|
kw[:stroke_color] = isa(strcolor, Array) ? first(strcolor) : strcolor
|
||||||
p = get(kw, :primitive, GeometryTypes.Circle)
|
p = get(kw, :primitive, GeometryTypes.Circle)
|
||||||
if isa(p, GLNormalMesh)
|
if isa(p, GLNormalMesh)
|
||||||
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
|
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
|
||||||
@ -1436,6 +1432,9 @@ function label_scatter(d, w, ho)
|
|||||||
kw[:scale] = Vec3f0(w/2)
|
kw[:scale] = Vec3f0(w/2)
|
||||||
delete!(kw, :offset)
|
delete!(kw, :offset)
|
||||||
end
|
end
|
||||||
|
if isa(p, Array)
|
||||||
|
kw[:primitive] = GeometryTypes.Circle
|
||||||
|
end
|
||||||
GL.gl_scatter(Point2f0[(w/2, ho)], kw)
|
GL.gl_scatter(Point2f0[(w/2, ho)], kw)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -172,6 +172,8 @@ function gr_polyline(x, y, func = GR.polyline; arrowside=:none)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
|
||||||
|
|
||||||
function gr_inqtext(x, y, s)
|
function gr_inqtext(x, y, s)
|
||||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||||
GR.inqtextext(x, y, s[2:end-1])
|
GR.inqtextext(x, y, s[2:end-1])
|
||||||
@ -182,6 +184,8 @@ function gr_inqtext(x, y, s)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gr_text(x, y, s::Symbol) = gr_text(x, y, string(s))
|
||||||
|
|
||||||
function gr_text(x, y, s)
|
function gr_text(x, y, s)
|
||||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||||
GR.mathtex(x, y, s[2:end-1])
|
GR.mathtex(x, y, s[2:end-1])
|
||||||
@ -283,7 +287,8 @@ end
|
|||||||
# draw ONE symbol marker
|
# draw ONE symbol marker
|
||||||
function gr_draw_marker(xi, yi, msize::Number, shape::Symbol)
|
function gr_draw_marker(xi, yi, msize::Number, shape::Symbol)
|
||||||
GR.setmarkertype(gr_markertype[shape])
|
GR.setmarkertype(gr_markertype[shape])
|
||||||
GR.setmarkersize(0.3msize)
|
w, h = gr_plot_size
|
||||||
|
GR.setmarkersize(0.3msize / ((w + h) * 0.001))
|
||||||
GR.polymarker([xi], [yi])
|
GR.polymarker([xi], [yi])
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -330,9 +335,10 @@ end
|
|||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
function gr_set_line(w, style, c) #, a)
|
function gr_set_line(lw, style, c) #, a)
|
||||||
GR.setlinetype(gr_linetype[style])
|
GR.setlinetype(gr_linetype[style])
|
||||||
GR.setlinewidth(w)
|
w, h = gr_plot_size
|
||||||
|
GR.setlinewidth(max(0, lw / ((w + h) * 0.001)))
|
||||||
gr_set_linecolor(c) #, a)
|
gr_set_linecolor(c) #, a)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -421,7 +427,7 @@ end
|
|||||||
function gr_colorbar(sp::Subplot)
|
function gr_colorbar(sp::Subplot)
|
||||||
if sp[:colorbar] != :none
|
if sp[:colorbar] != :none
|
||||||
gr_set_viewport_cmap(sp)
|
gr_set_viewport_cmap(sp)
|
||||||
GR.colormap()
|
GR.colorbar()
|
||||||
gr_set_viewport_plotarea()
|
gr_set_viewport_plotarea()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -545,6 +551,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
end
|
end
|
||||||
if st == :heatmap
|
if st == :heatmap
|
||||||
outside_ticks = true
|
outside_ticks = true
|
||||||
|
x, y = heatmap_edges(series[:x]), heatmap_edges(series[:y])
|
||||||
|
expand_extrema!(sp[:xaxis], x)
|
||||||
|
expand_extrema!(sp[:yaxis], y)
|
||||||
|
data_lims = gr_xy_axislims(sp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -653,6 +663,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
flip = sp[:yaxis][:flip]
|
flip = sp[:yaxis][:flip]
|
||||||
mirror = sp[:xaxis][:mirror]
|
mirror = sp[:xaxis][:mirror]
|
||||||
gr_set_font(sp[:xaxis][:tickfont],
|
gr_set_font(sp[:xaxis][:tickfont],
|
||||||
|
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
|
||||||
valign = (mirror ? :bottom : :top),
|
valign = (mirror ? :bottom : :top),
|
||||||
color = sp[:xaxis][:foreground_color_axis],
|
color = sp[:xaxis][:foreground_color_axis],
|
||||||
rotation = sp[:xaxis][:rotation])
|
rotation = sp[:xaxis][:rotation])
|
||||||
@ -670,6 +681,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
mirror = sp[:yaxis][:mirror]
|
mirror = sp[:yaxis][:mirror]
|
||||||
gr_set_font(sp[:yaxis][:tickfont],
|
gr_set_font(sp[:yaxis][:tickfont],
|
||||||
halign = (mirror ? :left : :right),
|
halign = (mirror ? :left : :right),
|
||||||
|
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
|
||||||
color = sp[:yaxis][:foreground_color_axis],
|
color = sp[:yaxis][:foreground_color_axis],
|
||||||
rotation = sp[:yaxis][:rotation])
|
rotation = sp[:yaxis][:rotation])
|
||||||
for (cv, dv) in zip(yticks...)
|
for (cv, dv) in zip(yticks...)
|
||||||
@ -757,10 +769,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
# recompute data
|
# recompute data
|
||||||
if typeof(z) <: Surface
|
if typeof(z) <: Surface
|
||||||
# if st == :heatmap
|
|
||||||
# expand_extrema!(sp[:xaxis], (x[1]-0.5*(x[2]-x[1]), x[end]+0.5*(x[end]-x[end-1])))
|
|
||||||
# expand_extrema!(sp[:yaxis], (y[1]-0.5*(y[2]-y[1]), y[end]+0.5*(y[end]-y[end-1])))
|
|
||||||
# end
|
|
||||||
z = vec(transpose_z(series, z.surf, false))
|
z = vec(transpose_z(series, z.surf, false))
|
||||||
elseif ispolar(sp)
|
elseif ispolar(sp)
|
||||||
if frng != nothing
|
if frng != nothing
|
||||||
@ -805,12 +813,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
isfinite(clims[1]) && (zmin = clims[1])
|
isfinite(clims[1]) && (zmin = clims[1])
|
||||||
isfinite(clims[2]) && (zmax = clims[2])
|
isfinite(clims[2]) && (zmax = clims[2])
|
||||||
end
|
end
|
||||||
|
GR.setspace(zmin, zmax, 0, 90)
|
||||||
if typeof(series[:levels]) <: Array
|
if typeof(series[:levels]) <: Array
|
||||||
h = series[:levels]
|
h = series[:levels]
|
||||||
else
|
else
|
||||||
h = linspace(zmin, zmax, series[:levels])
|
h = linspace(zmin, zmax, series[:levels])
|
||||||
end
|
end
|
||||||
GR.setspace(zmin, zmax, 0, 90)
|
|
||||||
if series[:fillrange] != nothing
|
if series[:fillrange] != nothing
|
||||||
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
||||||
else
|
else
|
||||||
@ -848,6 +856,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
isfinite(clims[1]) && (zmin = clims[1])
|
isfinite(clims[1]) && (zmin = clims[1])
|
||||||
isfinite(clims[2]) && (zmax = clims[2])
|
isfinite(clims[2]) && (zmax = clims[2])
|
||||||
end
|
end
|
||||||
|
GR.setspace(zmin, zmax, 0, 90)
|
||||||
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad()
|
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad()
|
||||||
colors = [grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)] for zi=z]
|
colors = [grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)] for zi=z]
|
||||||
rgba = map(c -> UInt32( round(Int, alpha(c) * 255) << 24 +
|
rgba = map(c -> UInt32( round(Int, alpha(c) * 255) << 24 +
|
||||||
@ -942,7 +951,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
elseif st == :image
|
elseif st == :image
|
||||||
z = transpose_z(series, series[:z].surf, true)
|
z = transpose_z(series, series[:z].surf, true)
|
||||||
h, w = size(z)
|
w, h = size(z)
|
||||||
if eltype(z) <: Colors.AbstractGray
|
if eltype(z) <: Colors.AbstractGray
|
||||||
grey = round(UInt8, float(z) * 255)
|
grey = round(UInt8, float(z) * 255)
|
||||||
rgba = map(c -> UInt32( 0xff000000 + Int(c)<<16 + Int(c)<<8 + Int(c) ), grey)
|
rgba = map(c -> UInt32( 0xff000000 + Int(c)<<16 + Int(c)<<8 + Int(c) ), grey)
|
||||||
@ -1015,7 +1024,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if series[:markershape] != :none
|
if series[:markershape] != :none
|
||||||
gr_draw_markers(series, xpos-[0.06,0.02], [ypos,ypos], 10, nothing)
|
gr_draw_markers(series, xpos - .035, ypos, 6, nothing)
|
||||||
end
|
end
|
||||||
|
|
||||||
if typeof(series[:label]) <: Array
|
if typeof(series[:label]) <: Array
|
||||||
@ -1101,7 +1110,7 @@ function _display(plt::Plot{GRBackend})
|
|||||||
ENV["GKS_FILEPATH"] = filepath
|
ENV["GKS_FILEPATH"] = filepath
|
||||||
gr_display(plt)
|
gr_display(plt)
|
||||||
GR.emergencyclosegks()
|
GR.emergencyclosegks()
|
||||||
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(readbytes, filepath)), "\a")
|
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(read, filepath)), "\a")
|
||||||
println(content)
|
println(content)
|
||||||
rm(filepath)
|
rm(filepath)
|
||||||
else
|
else
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const _inspectdr_attr = merge_with_base_supported([
|
|||||||
# :ribbon, :quiver, :arrow,
|
# :ribbon, :quiver, :arrow,
|
||||||
# :orientation,
|
# :orientation,
|
||||||
:overwrite_figure,
|
:overwrite_figure,
|
||||||
# :polar,
|
:polar,
|
||||||
# :normalize, :weights,
|
# :normalize, :weights,
|
||||||
# :contours, :aspect_ratio,
|
# :contours, :aspect_ratio,
|
||||||
:match_dimensions,
|
:match_dimensions,
|
||||||
@ -66,6 +66,9 @@ const _inspectdr_scale = [:identity, :ln, :log2, :log10]
|
|||||||
|
|
||||||
is_marker_supported(::InspectDRBackend, shape::Shape) = true
|
is_marker_supported(::InspectDRBackend, shape::Shape) = true
|
||||||
|
|
||||||
|
_inspectdr_to_pixels(bb::BoundingBox) =
|
||||||
|
InspectDR.BoundingBox(to_pixels(left(bb)), to_pixels(right(bb)), to_pixels(top(bb)), to_pixels(bottom(bb)))
|
||||||
|
|
||||||
#Do we avoid Map to avoid possible pre-comile issues?
|
#Do we avoid Map to avoid possible pre-comile issues?
|
||||||
function _inspectdr_mapglyph(s::Symbol)
|
function _inspectdr_mapglyph(s::Symbol)
|
||||||
s == :rect && return :square
|
s == :rect && return :square
|
||||||
@ -125,16 +128,17 @@ end
|
|||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function _inspectdr_getscale(s::Symbol)
|
function _inspectdr_getscale(s::Symbol, yaxis::Bool)
|
||||||
#TODO: Support :asinh, :sqrt
|
#TODO: Support :asinh, :sqrt
|
||||||
|
kwargs = yaxis? (:tgtmajor=>8, :tgtminor=>2): () #More grid lines on y-axis
|
||||||
if :log2 == s
|
if :log2 == s
|
||||||
return InspectDR.AxisScale(:log2)
|
return InspectDR.AxisScale(:log2; kwargs...)
|
||||||
elseif :log10 == s
|
elseif :log10 == s
|
||||||
return InspectDR.AxisScale(:log10)
|
return InspectDR.AxisScale(:log10; kwargs...)
|
||||||
elseif :ln == s
|
elseif :ln == s
|
||||||
return InspectDR.AxisScale(:ln)
|
return InspectDR.AxisScale(:ln; kwargs...)
|
||||||
else #identity
|
else #identity
|
||||||
return InspectDR.AxisScale(:lin)
|
return InspectDR.AxisScale(:lin; kwargs...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -209,14 +213,10 @@ end
|
|||||||
# Set up the subplot within the backend object.
|
# Set up the subplot within the backend object.
|
||||||
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
|
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
|
||||||
plot = sp.o
|
plot = sp.o
|
||||||
|
|
||||||
#Don't do anything without a "subplot" object: Will process later.
|
#Don't do anything without a "subplot" object: Will process later.
|
||||||
if nothing == plot; return; end
|
if nothing == plot; return; end
|
||||||
plot.data = []
|
plot.data = []
|
||||||
plot.markers = [] #Clear old markers
|
plot.userannot = [] #Clear old markers/text annotation/polyline "annotation"
|
||||||
plot.atext = [] #Clear old annotation
|
|
||||||
plot.apline = [] #Clear old poly lines
|
|
||||||
|
|
||||||
return plot
|
return plot
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -237,6 +237,12 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
|
|||||||
_vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors
|
_vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors
|
||||||
x = _vectorize(series[:x]); y = _vectorize(series[:y])
|
x = _vectorize(series[:x]); y = _vectorize(series[:y])
|
||||||
|
|
||||||
|
#No support for polar grid... but can still perform polar transformation:
|
||||||
|
if ispolar(sp)
|
||||||
|
Θ = x; r = y
|
||||||
|
x = r.*cos(Θ); y = r.*sin(Θ)
|
||||||
|
end
|
||||||
|
|
||||||
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
|
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
|
||||||
nx = length(x); ny = length(y)
|
nx = length(x); ny = length(y)
|
||||||
if nx < ny
|
if nx < ny
|
||||||
@ -267,7 +273,7 @@ For st in :shape:
|
|||||||
apline = InspectDR.PolylineAnnotation(
|
apline = InspectDR.PolylineAnnotation(
|
||||||
x[rng], y[rng], line=line, fillcolor=fillcolor
|
x[rng], y[rng], line=line, fillcolor=fillcolor
|
||||||
)
|
)
|
||||||
push!(plot.apline, apline)
|
InspectDR.add(plot, apline)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -328,23 +334,35 @@ end
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
|
function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
|
||||||
const gridon = InspectDR.grid(vmajor=true, hmajor=true)
|
const gridon = InspectDR.GridRect(vmajor=true, hmajor=true)
|
||||||
const gridoff = InspectDR.grid()
|
const gridoff = InspectDR.GridRect()
|
||||||
const plot = sp.o
|
const plot = sp.o
|
||||||
|
const strip = plot.strips[1] #Only 1 strip supported with Plots.jl
|
||||||
|
|
||||||
|
#No independent control of grid???
|
||||||
|
strip.grid = sp[:grid]? gridon: gridoff
|
||||||
|
|
||||||
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
|
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
|
||||||
xscale = _inspectdr_getscale(xaxis[:scale])
|
plot.xscale = _inspectdr_getscale(xaxis[:scale], false)
|
||||||
yscale = _inspectdr_getscale(yaxis[:scale])
|
strip.yscale = _inspectdr_getscale(yaxis[:scale], true)
|
||||||
plot.axes = InspectDR.AxesRect(xscale, yscale)
|
|
||||||
xmin, xmax = axis_limits(xaxis)
|
xmin, xmax = axis_limits(xaxis)
|
||||||
ymin, ymax = axis_limits(yaxis)
|
ymin, ymax = axis_limits(yaxis)
|
||||||
plot.ext = InspectDR.PExtents2D() #reset
|
if ispolar(sp)
|
||||||
plot.ext_full = InspectDR.PExtents2D(xmin, xmax, ymin, ymax)
|
#Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax)
|
||||||
|
rmax = max(abs(ymin), abs(ymax))
|
||||||
|
xmin, xmax = -rmax, rmax
|
||||||
|
ymin, ymax = -rmax, rmax
|
||||||
|
end
|
||||||
|
plot.xext = InspectDR.PExtents1D() #reset
|
||||||
|
strip.yext = InspectDR.PExtents1D() #reset
|
||||||
|
plot.xext_full = InspectDR.PExtents1D(xmin, xmax)
|
||||||
|
strip.yext_full = InspectDR.PExtents1D(ymin, ymax)
|
||||||
a = plot.annotation
|
a = plot.annotation
|
||||||
a.title = sp[:title]
|
a.title = sp[:title]
|
||||||
a.xlabel = xaxis[:guide]; a.ylabel = yaxis[:guide]
|
a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]]
|
||||||
|
|
||||||
l = plot.layout
|
l = plot.layout
|
||||||
|
l.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
|
||||||
l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
|
l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
|
||||||
l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
|
l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
|
||||||
l.fnttitle = InspectDR.Font(sp[:titlefont].family,
|
l.fnttitle = InspectDR.Font(sp[:titlefont].family,
|
||||||
@ -360,8 +378,6 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
|
|||||||
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
|
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
|
||||||
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
|
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
|
||||||
)
|
)
|
||||||
#No independent control of grid???
|
|
||||||
l.grid = sp[:grid]? gridon: gridoff
|
|
||||||
leg = l.legend
|
leg = l.legend
|
||||||
leg.enabled = (sp[:legend] != :none)
|
leg.enabled = (sp[:legend] != :none)
|
||||||
#leg.width = 150 #TODO: compute???
|
#leg.width = 150 #TODO: compute???
|
||||||
@ -378,6 +394,13 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
|
|||||||
const mplot = _inspectdr_getmplot(plt.o)
|
const mplot = _inspectdr_getmplot(plt.o)
|
||||||
if nothing == mplot; return; end
|
if nothing == mplot; return; end
|
||||||
|
|
||||||
|
mplot.title = plt[:plot_title]
|
||||||
|
if "" == mplot.title
|
||||||
|
#Don't use window_title... probably not what you want.
|
||||||
|
#mplot.title = plt[:window_title]
|
||||||
|
end
|
||||||
|
mplot.frame.fillcolor = _inspectdr_mapcolor(plt[:background_color_outside])
|
||||||
|
|
||||||
resize!(mplot.subplots, length(plt.subplots))
|
resize!(mplot.subplots, length(plt.subplots))
|
||||||
nsubplots = length(plt.subplots)
|
nsubplots = length(plt.subplots)
|
||||||
for (i, sp) in enumerate(plt.subplots)
|
for (i, sp) in enumerate(plt.subplots)
|
||||||
@ -385,15 +408,13 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
|
|||||||
mplot.subplots[i] = InspectDR.Plot2D()
|
mplot.subplots[i] = InspectDR.Plot2D()
|
||||||
end
|
end
|
||||||
sp.o = mplot.subplots[i]
|
sp.o = mplot.subplots[i]
|
||||||
|
plot = sp.o
|
||||||
_initialize_subplot(plt, sp)
|
_initialize_subplot(plt, sp)
|
||||||
_inspectdr_setupsubplot(sp)
|
_inspectdr_setupsubplot(sp)
|
||||||
|
|
||||||
sp.o.layout.frame.fillcolor =
|
|
||||||
_inspectdr_mapcolor(plt[:background_color_outside])
|
|
||||||
|
|
||||||
# add the annotations
|
# add the annotations
|
||||||
for ann in sp[:annotations]
|
for ann in sp[:annotations]
|
||||||
_inspectdr_add_annotations(mplot.subplots[i], ann...)
|
_inspectdr_add_annotations(plot, ann...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -422,8 +443,19 @@ end
|
|||||||
# Set the (left, top, right, bottom) minimum padding around the plot area
|
# Set the (left, top, right, bottom) minimum padding around the plot area
|
||||||
# to fit ticks, tick labels, guides, colorbars, etc.
|
# to fit ticks, tick labels, guides, colorbars, etc.
|
||||||
function _update_min_padding!(sp::Subplot{InspectDRBackend})
|
function _update_min_padding!(sp::Subplot{InspectDRBackend})
|
||||||
sp.minpad = (20mm, 5mm, 2mm, 10mm)
|
plot = sp.o
|
||||||
#TODO: Add support for padding.
|
if !isa(plot, InspectDR.Plot2D); return sp.minpad; end
|
||||||
|
#Computing plotbounds with 0-BoundingBox returns required padding:
|
||||||
|
bb = InspectDR.plotbounds(plot.layout, InspectDR.BoundingBox(0,0,0,0))
|
||||||
|
#NOTE: plotbounds always pads for titles, legends, etc. even if not in use.
|
||||||
|
#TODO: possibly zero-out items not in use??
|
||||||
|
|
||||||
|
# add in the user-specified margin to InspectDR padding:
|
||||||
|
leftpad = abs(bb.xmin)*px + sp[:left_margin]
|
||||||
|
toppad = abs(bb.ymin)*px + sp[:top_margin]
|
||||||
|
rightpad = abs(bb.xmax)*px + sp[:right_margin]
|
||||||
|
bottompad = abs(bb.ymax)*px + sp[:bottom_margin]
|
||||||
|
sp.minpad = (leftpad, toppad, rightpad, bottompad)
|
||||||
end
|
end
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
@ -432,6 +464,13 @@ end
|
|||||||
function _update_plot_object(plt::Plot{InspectDRBackend})
|
function _update_plot_object(plt::Plot{InspectDRBackend})
|
||||||
mplot = _inspectdr_getmplot(plt.o)
|
mplot = _inspectdr_getmplot(plt.o)
|
||||||
if nothing == mplot; return; end
|
if nothing == mplot; return; end
|
||||||
|
|
||||||
|
for (i, sp) in enumerate(plt.subplots)
|
||||||
|
graphbb = _inspectdr_to_pixels(plotarea(sp))
|
||||||
|
plot = mplot.subplots[i]
|
||||||
|
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
|
||||||
|
end
|
||||||
|
|
||||||
gplot = _inspectdr_getgui(plt.o)
|
gplot = _inspectdr_getgui(plt.o)
|
||||||
if nothing == gplot; return; end
|
if nothing == gplot; return; end
|
||||||
|
|
||||||
@ -452,19 +491,21 @@ const _inspectdr_mimeformats_nodpi = Dict(
|
|||||||
# "application/postscript" => "ps", #TODO: support once Cairo supports PSSurface
|
# "application/postscript" => "ps", #TODO: support once Cairo supports PSSurface
|
||||||
"application/pdf" => "pdf"
|
"application/pdf" => "pdf"
|
||||||
)
|
)
|
||||||
_inspectdr_show(io::IO, mime::MIME, ::Void) =
|
_inspectdr_show(io::IO, mime::MIME, ::Void, w, h) =
|
||||||
throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated"))
|
throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated"))
|
||||||
_inspectdr_show(io::IO, mime::MIME, mplot) = show(io, mime, mplot)
|
function _inspectdr_show(io::IO, mime::MIME, mplot, w, h)
|
||||||
|
InspectDR._show(io, mime, mplot, Float64(w), Float64(h))
|
||||||
|
end
|
||||||
|
|
||||||
for (mime, fmt) in _inspectdr_mimeformats_dpi
|
for (mime, fmt) in _inspectdr_mimeformats_dpi
|
||||||
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
|
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
|
||||||
dpi = plt[:dpi]#TODO: support
|
dpi = plt[:dpi]#TODO: support
|
||||||
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o))
|
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for (mime, fmt) in _inspectdr_mimeformats_nodpi
|
for (mime, fmt) in _inspectdr_mimeformats_nodpi
|
||||||
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
|
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
|
||||||
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o))
|
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
_show(io::IO, mime::MIME"text/plain", plt::Plot{InspectDRBackend}) = nothing #Don't show
|
_show(io::IO, mime::MIME"text/plain", plt::Plot{InspectDRBackend}) = nothing #Don't show
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
# significant contributions by: @pkofod
|
# significant contributions by: @pkofod
|
||||||
|
|
||||||
const _pgfplots_attr = merge_with_base_supported([
|
const _pgfplots_attr = merge_with_base_supported([
|
||||||
# :annotations,
|
:annotations,
|
||||||
# :background_color_legend,
|
# :background_color_legend,
|
||||||
:background_color_inside,
|
:background_color_inside,
|
||||||
# :background_color_outside,
|
# :background_color_outside,
|
||||||
@ -22,17 +22,17 @@ const _pgfplots_attr = merge_with_base_supported([
|
|||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:tickfont, :guidefont, :legendfont,
|
||||||
:grid, :legend,
|
:grid, :legend,
|
||||||
# :colorbar,
|
:colorbar,
|
||||||
# :marker_z, :levels,
|
:marker_z, #:levels,
|
||||||
# :ribbon, :quiver, :arrow,
|
# :ribbon, :quiver, :arrow,
|
||||||
# :orientation,
|
# :orientation,
|
||||||
# :overwrite_figure,
|
# :overwrite_figure,
|
||||||
# :polar,
|
:polar,
|
||||||
# :normalize, :weights, :contours,
|
# :normalize, :weights, :contours,
|
||||||
:aspect_ratio,
|
:aspect_ratio,
|
||||||
# :match_dimensions,
|
# :match_dimensions,
|
||||||
])
|
])
|
||||||
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour]
|
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape]
|
||||||
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||||
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape)
|
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape)
|
||||||
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
||||||
@ -98,14 +98,35 @@ const _pgf_series_extrastyle = KW(
|
|||||||
:xsticks => "xcomb",
|
:xsticks => "xcomb",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# PGFPlots uses the anchors to define orientations for example to align left
|
||||||
|
# one needs to use the right edge as anchor
|
||||||
|
const _pgf_annotation_halign = KW(
|
||||||
|
:center => "",
|
||||||
|
:left => "right",
|
||||||
|
:right => "left"
|
||||||
|
)
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# takes in color,alpha, and returns color and alpha appropriate for pgf style
|
# takes in color,alpha, and returns color and alpha appropriate for pgf style
|
||||||
function pgf_color(c)
|
function pgf_color(c::Colorant)
|
||||||
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c))
|
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c))
|
||||||
cstr, alpha(c)
|
cstr, alpha(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function pgf_color(grad::ColorGradient)
|
||||||
|
# Can't handle ColorGradient here, fallback to defaults.
|
||||||
|
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012)
|
||||||
|
cstr, 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generates a colormap for pgfplots based on a ColorGradient
|
||||||
|
function pgf_colormap(grad::ColorGradient)
|
||||||
|
join(map(grad.colors) do c
|
||||||
|
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c))
|
||||||
|
end,", ")
|
||||||
|
end
|
||||||
|
|
||||||
function pgf_fillstyle(d::KW)
|
function pgf_fillstyle(d::KW)
|
||||||
cstr,a = pgf_color(d[:fillcolor])
|
cstr,a = pgf_color(d[:fillcolor])
|
||||||
"fill = $cstr, fill opacity=$a"
|
"fill = $cstr, fill opacity=$a"
|
||||||
@ -136,6 +157,19 @@ function pgf_marker(d::KW)
|
|||||||
}"""
|
}"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function pgf_add_annotation!(o,x,y,val)
|
||||||
|
# Construct the style string.
|
||||||
|
# Currently supports color and orientation
|
||||||
|
cstr,a = pgf_color(val.font.color)
|
||||||
|
push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text
|
||||||
|
x, y,
|
||||||
|
style="""
|
||||||
|
$(get(_pgf_annotation_halign,val.font.halign,"")),
|
||||||
|
color=$cstr, draw opacity=$(convert(Float16,a)),
|
||||||
|
rotate=$(val.font.rotation)
|
||||||
|
"""))
|
||||||
|
end
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
function pgf_series(sp::Subplot, series::Series)
|
function pgf_series(sp::Subplot, series::Series)
|
||||||
@ -143,11 +177,10 @@ function pgf_series(sp::Subplot, series::Series)
|
|||||||
st = d[:seriestype]
|
st = d[:seriestype]
|
||||||
style = []
|
style = []
|
||||||
kw = KW()
|
kw = KW()
|
||||||
|
|
||||||
push!(style, pgf_linestyle(d))
|
push!(style, pgf_linestyle(d))
|
||||||
push!(style, pgf_marker(d))
|
push!(style, pgf_marker(d))
|
||||||
|
|
||||||
if d[:fillrange] != nothing
|
if d[:fillrange] != nothing || st in (:shape,)
|
||||||
push!(style, pgf_fillstyle(d))
|
push!(style, pgf_fillstyle(d))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -163,6 +196,10 @@ function pgf_series(sp::Subplot, series::Series)
|
|||||||
d[:z].surf, d[:x], d[:y]
|
d[:z].surf, d[:x], d[:y]
|
||||||
elseif is3d(st)
|
elseif is3d(st)
|
||||||
d[:x], d[:y], d[:z]
|
d[:x], d[:y], d[:z]
|
||||||
|
elseif d[:marker_z] != nothing
|
||||||
|
# If a marker_z is used pass it as third coordinate to a 2D plot.
|
||||||
|
# See "Scatter Plots" in PGFPlots documentation
|
||||||
|
d[:x], d[:y], d[:marker_z]
|
||||||
else
|
else
|
||||||
d[:x], d[:y]
|
d[:x], d[:y]
|
||||||
end
|
end
|
||||||
@ -211,6 +248,9 @@ function pgf_axis(sp::Subplot, letter)
|
|||||||
# axis guide
|
# axis guide
|
||||||
kw[Symbol(letter,:label)] = axis[:guide]
|
kw[Symbol(letter,:label)] = axis[:guide]
|
||||||
|
|
||||||
|
# Add ticklabel rotations
|
||||||
|
push!(style, "$(letter)ticklabel style={rotate = $(axis[:rotation])}")
|
||||||
|
|
||||||
# flip/reverse?
|
# flip/reverse?
|
||||||
axis[:flip] && push!(style, "$letter dir=reverse")
|
axis[:flip] && push!(style, "$letter dir=reverse")
|
||||||
|
|
||||||
@ -249,8 +289,12 @@ end
|
|||||||
|
|
||||||
function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
||||||
plt.o = PGFPlots.Axis[]
|
plt.o = PGFPlots.Axis[]
|
||||||
|
# Obtain the total height of the plot by extracting the maximal bottom
|
||||||
|
# coordinate from the bounding box.
|
||||||
|
total_height = bottom(bbox(plt.layout))
|
||||||
|
|
||||||
for sp in plt.subplots
|
for sp in plt.subplots
|
||||||
# first build the PGFPlots.Axis object
|
# first build the PGFPlots.Axis object
|
||||||
style = ["unbounded coords=jump"]
|
style = ["unbounded coords=jump"]
|
||||||
kw = KW()
|
kw = KW()
|
||||||
|
|
||||||
@ -265,10 +309,12 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
|||||||
|
|
||||||
# bounding box values are in mm
|
# bounding box values are in mm
|
||||||
# note: bb origin is top-left, pgf is bottom-left
|
# note: bb origin is top-left, pgf is bottom-left
|
||||||
|
# A round on 2 decimal places should be enough precision for 300 dpi
|
||||||
|
# plots.
|
||||||
bb = bbox(sp)
|
bb = bbox(sp)
|
||||||
push!(style, """
|
push!(style, """
|
||||||
xshift = $(left(bb).value)mm,
|
xshift = $(left(bb).value)mm,
|
||||||
yshift = $((height(bb) - (bottom(bb))).value)mm,
|
yshift = $(round((total_height - (bottom(bb))).value,2))mm,
|
||||||
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
|
axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])}
|
||||||
""")
|
""")
|
||||||
kw[:width] = "$(width(bb).value)mm"
|
kw[:width] = "$(width(bb).value)mm"
|
||||||
@ -288,19 +334,62 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
|||||||
kw[:legendPos] = _pgfplots_legend_pos[legpos]
|
kw[:legendPos] = _pgfplots_legend_pos[legpos]
|
||||||
end
|
end
|
||||||
|
|
||||||
o = PGFPlots.Axis(; style = style, kw...)
|
axisf = PGFPlots.Axis
|
||||||
|
if sp[:projection] == :polar
|
||||||
|
axisf = PGFPlots.PolarAxis
|
||||||
|
end
|
||||||
|
|
||||||
|
# Search series for any gradient. In case one series uses a gradient set
|
||||||
|
# the colorbar and colomap.
|
||||||
|
# The reasoning behind doing this on the axis level is that pgfplots
|
||||||
|
# colorbar seems to only works on axis level and needs the proper colormap for
|
||||||
|
# correctly displaying it.
|
||||||
|
# It's also possible to assign the colormap to the series itself but
|
||||||
|
# then the colormap needs to be added twice, once for the axis and once for the
|
||||||
|
# series.
|
||||||
|
# As it is likely that all series within the same axis use the same
|
||||||
|
# colormap this should not cause any problem.
|
||||||
|
for series in series_list(sp)
|
||||||
|
for col in (:markercolor, :fillcolor)
|
||||||
|
if typeof(series.d[col]) == ColorGradient
|
||||||
|
push!(style,"colormap={plots}{$(pgf_colormap(series.d[col]))}")
|
||||||
|
|
||||||
|
if sp[:colorbar] == :none
|
||||||
|
kw[:colorbar] = "false"
|
||||||
|
else
|
||||||
|
kw[:colorbar] = "true"
|
||||||
|
end
|
||||||
|
# goto is needed to break out of col and series for
|
||||||
|
@goto colorbar_end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@label colorbar_end
|
||||||
|
|
||||||
|
o = axisf(; style = style, kw...)
|
||||||
|
|
||||||
# add the series object to the PGFPlots.Axis
|
# add the series object to the PGFPlots.Axis
|
||||||
for series in series_list(sp)
|
for series in series_list(sp)
|
||||||
push!(o, pgf_series(sp, series))
|
push!(o, pgf_series(sp, series))
|
||||||
|
|
||||||
|
# add series annotations
|
||||||
|
anns = series[:series_annotations]
|
||||||
|
for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y])
|
||||||
|
pgf_add_annotation!(o, xi, yi, PlotText(str, fnt))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# add the annotations
|
||||||
|
for ann in sp[:annotations]
|
||||||
|
pgf_add_annotation!(o,ann...)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# add the PGFPlots.Axis to the list
|
# add the PGFPlots.Axis to the list
|
||||||
push!(plt.o, o)
|
push!(plt.o, o)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function _show(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend})
|
function _show(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend})
|
||||||
show(io, mime, plt.o)
|
show(io, mime, plt.o)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const _plotly_attr = merge_with_base_supported([
|
|||||||
:window_title,
|
:window_title,
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:tickfont, :guidefont, :legendfont,
|
||||||
:grid, :legend, :colorbar,
|
:grid, :legend, :colorbar, :colorbar_title,
|
||||||
:marker_z, :fill_z, :levels,
|
:marker_z, :fill_z, :levels,
|
||||||
:ribbon, :quiver,
|
:ribbon, :quiver,
|
||||||
:orientation,
|
:orientation,
|
||||||
@ -31,6 +31,7 @@ const _plotly_attr = merge_with_base_supported([
|
|||||||
:hover,
|
:hover,
|
||||||
:inset_subplots,
|
:inset_subplots,
|
||||||
:bar_width,
|
:bar_width,
|
||||||
|
:clims,
|
||||||
])
|
])
|
||||||
|
|
||||||
const _plotly_seriestype = [
|
const _plotly_seriestype = [
|
||||||
@ -268,7 +269,7 @@ function plotly_layout(plt::Plot)
|
|||||||
w, h = plt[:size]
|
w, h = plt[:size]
|
||||||
d_out[:width], d_out[:height] = w, h
|
d_out[:width], d_out[:height] = w, h
|
||||||
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
|
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
|
||||||
d_out[:margin] = KW(:l=>0, :b=>0, :r=>0, :t=>20)
|
d_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20)
|
||||||
|
|
||||||
d_out[:annotations] = KW[]
|
d_out[:annotations] = KW[]
|
||||||
|
|
||||||
@ -408,6 +409,10 @@ plotly_surface_data(series::Series, a::AbstractVector) = a
|
|||||||
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
|
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
|
||||||
plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf)
|
plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf)
|
||||||
|
|
||||||
|
#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
|
||||||
|
as_gradient(grad::ColorGradient, α) = grad
|
||||||
|
as_gradient(grad, α) = cgrad(alpha = α)
|
||||||
|
|
||||||
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
||||||
function plotly_series(plt::Plot, series::Series)
|
function plotly_series(plt::Plot, series::Series)
|
||||||
st = series[:seriestype]
|
st = series[:seriestype]
|
||||||
@ -438,6 +443,13 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
d_out[:colorbar] = KW(:title => sp[:colorbar_title])
|
||||||
|
|
||||||
|
clims = sp[:clims]
|
||||||
|
if is_2tuple(clims)
|
||||||
|
d_out[:zmin], d_out[:zmax] = clims
|
||||||
|
end
|
||||||
|
|
||||||
# set the "type"
|
# set the "type"
|
||||||
if st in (:path, :scatter, :scattergl)
|
if st in (:path, :scatter, :scattergl)
|
||||||
d_out[:type] = st==:scattergl ? "scattergl" : "scatter"
|
d_out[:type] = st==:scattergl ? "scattergl" : "scatter"
|
||||||
@ -533,9 +545,10 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
rgba_string(series[:markercolor])
|
rgba_string(series[:markercolor])
|
||||||
else
|
else
|
||||||
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
|
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
|
||||||
grad = series[:markercolor]
|
grad = as_gradient(series[:markercolor], series[:markeralpha])
|
||||||
zmin, zmax = extrema(series[:marker_z])
|
zmin, zmax = extrema(series[:marker_z])
|
||||||
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]]
|
zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
|
||||||
|
[rgba_string(grad[(zi - zmin) / zrange]) for zi in series[:marker_z]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -102,8 +102,18 @@ _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hac
|
|||||||
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf")
|
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf")
|
||||||
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps")
|
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps")
|
||||||
|
|
||||||
|
function write_temp_html(plt::Plot{PlotlyJSBackend})
|
||||||
|
filename = string(tempname(), ".html")
|
||||||
|
savefig(plt, filename)
|
||||||
|
filename
|
||||||
|
end
|
||||||
|
|
||||||
function _display(plt::Plot{PlotlyJSBackend})
|
function _display(plt::Plot{PlotlyJSBackend})
|
||||||
display(plt.o)
|
if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes")
|
||||||
|
display(plt.o)
|
||||||
|
else
|
||||||
|
standalone_html_window(plt)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,10 @@ function add_backend_string(::PyPlotBackend)
|
|||||||
withenv("PYTHON" => "") do
|
withenv("PYTHON" => "") do
|
||||||
Pkg.build("PyPlot")
|
Pkg.build("PyPlot")
|
||||||
end
|
end
|
||||||
|
import Conda
|
||||||
|
Conda.add("qt=4.8.5")
|
||||||
|
|
||||||
|
# now restart julia!
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -217,6 +221,12 @@ function py_stepstyle(seriestype::Symbol)
|
|||||||
return "default"
|
return "default"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function py_fillstepstyle(seriestype::Symbol)
|
||||||
|
seriestype == :steppost && return "post"
|
||||||
|
seriestype == :steppre && return "pre"
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
|
||||||
# # untested... return a FontProperties object from a Plots.Font
|
# # untested... return a FontProperties object from a Plots.Font
|
||||||
# function py_font(font::Font)
|
# function py_font(font::Font)
|
||||||
# pyfont.pymember("FontProperties")(
|
# pyfont.pymember("FontProperties")(
|
||||||
@ -669,6 +679,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
end
|
end
|
||||||
z = transpose_z(series, z)
|
z = transpose_z(series, z)
|
||||||
if st == :surface
|
if st == :surface
|
||||||
|
clims = sp[:clims]
|
||||||
|
if is_2tuple(clims)
|
||||||
|
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
|
||||||
|
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
|
||||||
|
end
|
||||||
if series[:fill_z] != nothing
|
if series[:fill_z] != nothing
|
||||||
# the surface colors are different than z-value
|
# the surface colors are different than z-value
|
||||||
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
|
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
|
||||||
@ -859,7 +874,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
dim1, expand_data(fillrange[1], n), expand_data(fillrange[2], n)
|
dim1, expand_data(fillrange[1], n), expand_data(fillrange[2], n)
|
||||||
end
|
end
|
||||||
|
|
||||||
handle = ax[f](args...;
|
handle = ax[f](args..., trues(n), false, py_fillstepstyle(st);
|
||||||
zorder = series[:series_plotindex],
|
zorder = series[:series_plotindex],
|
||||||
facecolor = py_fillcolor(series),
|
facecolor = py_fillcolor(series),
|
||||||
linewidths = 0
|
linewidths = 0
|
||||||
@ -1045,7 +1060,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
end
|
end
|
||||||
if sp[:grid]
|
if sp[:grid]
|
||||||
fgcolor = py_color(sp[:foreground_color_grid])
|
fgcolor = py_color(sp[:foreground_color_grid])
|
||||||
pyaxis[:grid](true, color = fgcolor)
|
pyaxis[:grid](true, color = fgcolor, linestyle = ":")
|
||||||
ax[:set_axisbelow](true)
|
ax[:set_axisbelow](true)
|
||||||
end
|
end
|
||||||
py_set_axis_colors(ax, axis)
|
py_set_axis_colors(ax, axis)
|
||||||
@ -1061,7 +1076,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
py_add_legend(plt, sp, ax)
|
py_add_legend(plt, sp, ax)
|
||||||
|
|
||||||
# this sets the bg color inside the grid
|
# this sets the bg color inside the grid
|
||||||
ax[:set_axis_bgcolor](py_color(sp[:background_color_inside]))
|
ax[:set_facecolor](py_color(sp[:background_color_inside]))
|
||||||
end
|
end
|
||||||
py_drawfig(fig)
|
py_drawfig(fig)
|
||||||
end
|
end
|
||||||
@ -1093,7 +1108,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
|
|||||||
# optionally add the width of colorbar labels and colorbar to rightpad
|
# optionally add the width of colorbar labels and colorbar to rightpad
|
||||||
if haskey(sp.attr, :cbar_ax)
|
if haskey(sp.attr, :cbar_ax)
|
||||||
bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]())
|
bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]())
|
||||||
sp.attr[:cbar_width] = _cbar_width + width(bb) + 1mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||||
rightpad = rightpad + sp.attr[:cbar_width]
|
rightpad = rightpad + sp.attr[:cbar_width]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -23,11 +23,11 @@ function open_browser_window(filename::AbstractString)
|
|||||||
@static if is_apple()
|
@static if is_apple()
|
||||||
return run(`open $(filename)`)
|
return run(`open $(filename)`)
|
||||||
end
|
end
|
||||||
@static if is_linux()
|
@static if is_linux() || is_bsd() # is_bsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681
|
||||||
return run(`xdg-open $(filename)`)
|
return run(`xdg-open $(filename)`)
|
||||||
end
|
end
|
||||||
@static if is_windows()
|
@static if is_windows()
|
||||||
return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
|
return run(`$(ENV["COMSPEC"]) /c start "" "$(filename)"`)
|
||||||
end
|
end
|
||||||
warn("Unknown OS... cannot open browser window.")
|
warn("Unknown OS... cannot open browser window.")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
typealias P2 StaticArrays.SVector{2,Float64}
|
const P2 = StaticArrays.SVector{2,Float64}
|
||||||
typealias P3 StaticArrays.SVector{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))
|
||||||
@ -174,7 +174,7 @@ function center(shape::Shape)
|
|||||||
Cx / 6A, Cy / 6A
|
Cx / 6A, Cy / 6A
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||||
sx, sy = coords(shape)
|
sx, sy = coords(shape)
|
||||||
cx, cy = c
|
cx, cy = c
|
||||||
for i=1:length(sx)
|
for i=1:length(sx)
|
||||||
@ -521,7 +521,7 @@ Base.Array(surf::Surface) = surf.surf
|
|||||||
for f in (:length, :size)
|
for f in (:length, :size)
|
||||||
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
||||||
end
|
end
|
||||||
Base.copy(surf::Surface) = Surface{typeof(surf.surf)}(copy(surf.surf))
|
Base.copy(surf::Surface) = Surface(copy(surf.surf))
|
||||||
Base.eltype{T}(surf::Surface{T}) = eltype(T)
|
Base.eltype{T}(surf::Surface{T}) = eltype(T)
|
||||||
|
|
||||||
function expand_extrema!(a::Axis, surf::Surface)
|
function expand_extrema!(a::Axis, surf::Surface)
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
# This should cut down on boilerplate code and allow more focused dispatch on type
|
# 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
|
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
|
||||||
|
|
||||||
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
|
const FuncOrFuncs = @compat(Union{Function, AVec{Function}})
|
||||||
|
|
||||||
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
||||||
|
|
||||||
|
|||||||
@ -172,6 +172,24 @@ PlotExample("",
|
|||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
|
PlotExample("Animation with subplots",
|
||||||
|
"The `layout` macro can be used to create an animation with subplots.",
|
||||||
|
[:(begin
|
||||||
|
l = @layout([[a; b] c])
|
||||||
|
p = plot(plot([sin,cos],1,leg=false),
|
||||||
|
scatter([atan,cos],1,leg=false),
|
||||||
|
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
|
||||||
|
|
||||||
|
anim = Animation()
|
||||||
|
for x = linspace(1,10π,100)
|
||||||
|
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
|
||||||
|
frame(anim)
|
||||||
|
end
|
||||||
|
end)]
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PlotExample("Open/High/Low/Close",
|
PlotExample("Open/High/Low/Close",
|
||||||
"Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.",
|
"Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.",
|
||||||
[:(begin
|
[:(begin
|
||||||
|
|||||||
@ -271,7 +271,7 @@ function setup_ijulia()
|
|||||||
show(io, MIME("text/html"), plt)
|
show(io, MIME("text/html"), plt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set_ijulia_output("text/html")
|
@eval set_ijulia_output("text/html")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -302,6 +302,10 @@ function setup_atom()
|
|||||||
Media.render(pane, Atom.div(".fill", Atom.HTML(stringmime(MIME("text/html"), plt))))
|
Media.render(pane, Atom.div(".fill", Atom.HTML(stringmime(MIME("text/html"), plt))))
|
||||||
plt[:size] = sz
|
plt[:size] = sz
|
||||||
end
|
end
|
||||||
|
# special handling for PlotlyJS
|
||||||
|
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend})
|
||||||
|
display(Plots.PlotsDisplay(), plt)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
#
|
#
|
||||||
function Media.render(pane::Atom.PlotPane, plt::Plot)
|
function Media.render(pane::Atom.PlotPane, plt::Plot)
|
||||||
@ -314,14 +318,8 @@ function setup_atom()
|
|||||||
# special handling for plotly... use PlotsDisplay
|
# special handling for plotly... use PlotsDisplay
|
||||||
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
|
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
|
||||||
display(Plots.PlotsDisplay(), plt)
|
display(Plots.PlotsDisplay(), plt)
|
||||||
s = "PlotPane turned off. The plotly and plotlyjs backends cannot render in the PlotPane due to javascript issues."
|
s = "PlotPane turned off. The plotly backend cannot render in the PlotPane due to javascript issues. Plotlyjs is similar to plotly and is compatible with the plot pane."
|
||||||
Media.render(pane, Atom.div(Atom.HTML(s)))
|
Media.render(pane, Atom.div(Atom.HTML(s)))
|
||||||
end
|
end
|
||||||
|
|
||||||
# special handling for PlotlyJS to pass through to that render method
|
|
||||||
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend})
|
|
||||||
Plots.prepare_output(plt)
|
|
||||||
Media.render(pane, plt.o)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -277,6 +277,13 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
|
|||||||
attr[Symbol(letter,k)] = v
|
attr[Symbol(letter,k)] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for k in (:scale,), letter in (:x,:y,:z)
|
||||||
|
# Series recipes may need access to this information
|
||||||
|
lk = Symbol(letter,k)
|
||||||
|
if haskey(attr, lk)
|
||||||
|
kw[lk] = attr[lk]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
sp_attrs[sp] = attr
|
sp_attrs[sp] = attr
|
||||||
end
|
end
|
||||||
@ -357,7 +364,7 @@ function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
|
|||||||
expand_extrema!(sp[:xaxis], (0,w))
|
expand_extrema!(sp[:xaxis], (0,w))
|
||||||
expand_extrema!(sp[:yaxis], (0,h))
|
expand_extrema!(sp[:yaxis], (0,h))
|
||||||
sp[:yaxis].d[:flip] = true
|
sp[:yaxis].d[:flip] = true
|
||||||
elseif !(st in (:pie, :histogram, :histogram2d))
|
elseif !(st in (:pie, :histogram, :bins2d, :histogram2d))
|
||||||
expand_extrema!(sp, d)
|
expand_extrema!(sp, d)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
56
src/plotattr.jl
Normal file
56
src/plotattr.jl
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
const _attribute_defaults = Dict(:Series => _series_defaults,
|
||||||
|
:Subplot => _subplot_defaults,
|
||||||
|
:Plot => _plot_defaults,
|
||||||
|
:Axis => _axis_defaults)
|
||||||
|
|
||||||
|
attrtypes() = join(keys(_attribute_defaults), ", ")
|
||||||
|
attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype])))
|
||||||
|
|
||||||
|
function lookup_aliases(attrtype, attribute)
|
||||||
|
attribute = Symbol(attribute)
|
||||||
|
attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute
|
||||||
|
in(attribute, keys(_attribute_defaults[attrtype])) && return attribute
|
||||||
|
error("There is no attribute named $attribute in $attrtype")
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotattr()
|
||||||
|
println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())")
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotattr(attrtype::Symbol)
|
||||||
|
in(attrtype, keys(_attribute_defaults)) || error("Viable options are $(attrtypes())")
|
||||||
|
println("Defined $attrtype attributes are:\n$(join(attributes(attrtype), ", "))")
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotattr(attribute::AbstractString)
|
||||||
|
attribute = Symbol(attribute)
|
||||||
|
attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute
|
||||||
|
for (k, v) in _attribute_defaults
|
||||||
|
if in(attribute, keys(v))
|
||||||
|
return plotattr(k, "$attribute")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
error("There is no attribute named $attribute")
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotattr(attrtype::Symbol, attribute::AbstractString)
|
||||||
|
in(attrtype, keys(_attribute_defaults)) || ArgumentError("`attrtype` must match one of $(attrtypes())")
|
||||||
|
|
||||||
|
attribute = Symbol(lookup_aliases(attrtype, attribute))
|
||||||
|
|
||||||
|
desc = get(_arg_desc, attribute, "")
|
||||||
|
first_period_idx = findfirst(desc, '.')
|
||||||
|
typedesc = desc[1:first_period_idx-1]
|
||||||
|
desc = strip(desc[first_period_idx+1:end])
|
||||||
|
als = keys(filter((_,v)->v==attribute, _keyAliases)) |> collect |> sort
|
||||||
|
als = join(map(string,als), ", ")
|
||||||
|
def = _attribute_defaults[attrtype][attribute]
|
||||||
|
|
||||||
|
|
||||||
|
# Looks up the different elements and plots them
|
||||||
|
println("$attribute ", typedesc == "" ? "" : "{$typedesc}", "\n",
|
||||||
|
als == "" ? "" : "$als\n",
|
||||||
|
"\n$desc\n",
|
||||||
|
"$(attrtype) attribute, ", def == "" ? "" : " default: $def")
|
||||||
|
end
|
||||||
453
src/recipes.jl
453
src/recipes.jl
@ -323,10 +323,11 @@ end
|
|||||||
|
|
||||||
# create a bar plot as a filled step function
|
# create a bar plot as a filled step function
|
||||||
@recipe function f(::Type{Val{:bar}}, x, y, z)
|
@recipe function f(::Type{Val{:bar}}, x, y, z)
|
||||||
nx, ny = length(x), length(y)
|
procx, procy, xscale, yscale, baseline = _preprocess_barlike(d, x, y)
|
||||||
|
nx, ny = length(procx), length(procy)
|
||||||
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
|
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
|
||||||
cv = [discrete_value!(axis, xi)[1] for xi=x]
|
cv = [discrete_value!(axis, xi)[1] for xi=procx]
|
||||||
x = if nx == ny
|
procx = if nx == ny
|
||||||
cv
|
cv
|
||||||
elseif nx == ny + 1
|
elseif nx == ny + 1
|
||||||
0.5diff(cv) + cv[1:end-1]
|
0.5diff(cv) + cv[1:end-1]
|
||||||
@ -337,9 +338,9 @@ end
|
|||||||
# compute half-width of bars
|
# compute half-width of bars
|
||||||
bw = d[:bar_width]
|
bw = d[:bar_width]
|
||||||
hw = if bw == nothing
|
hw = if bw == nothing
|
||||||
0.5mean(diff(x))
|
0.5mean(diff(procx))
|
||||||
else
|
else
|
||||||
Float64[0.5cycle(bw,i) for i=1:length(x)]
|
Float64[0.5cycle(bw,i) for i=1:length(procx)]
|
||||||
end
|
end
|
||||||
|
|
||||||
# make fillto a vector... default fills to 0
|
# make fillto a vector... default fills to 0
|
||||||
@ -347,16 +348,21 @@ end
|
|||||||
if fillto == nothing
|
if fillto == nothing
|
||||||
fillto = 0
|
fillto = 0
|
||||||
end
|
end
|
||||||
|
if (yscale in _logScales) && !all(_is_positive, fillto)
|
||||||
|
fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto)
|
||||||
|
end
|
||||||
|
|
||||||
# create the bar shapes by adding x/y segments
|
# create the bar shapes by adding x/y segments
|
||||||
xseg, yseg = Segments(), Segments()
|
xseg, yseg = Segments(), Segments()
|
||||||
for i=1:ny
|
for i=1:ny
|
||||||
center = x[i]
|
yi = procy[i]
|
||||||
hwi = cycle(hw,i)
|
if !isnan(yi)
|
||||||
yi = y[i]
|
center = procx[i]
|
||||||
fi = cycle(fillto,i)
|
hwi = cycle(hw,i)
|
||||||
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
|
fi = cycle(fillto,i)
|
||||||
push!(yseg, yi, fi, fi, yi, yi)
|
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
|
||||||
|
push!(yseg, yi, fi, fi, yi, yi)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# widen limits out a bit
|
# widen limits out a bit
|
||||||
@ -378,106 +384,327 @@ end
|
|||||||
end
|
end
|
||||||
@deps bar shape
|
@deps bar shape
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Histograms
|
# Histograms
|
||||||
|
|
||||||
# edges from number of bins
|
_bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2
|
||||||
function calc_edges(v, bins::Integer)
|
|
||||||
vmin, vmax = extrema(v)
|
_is_positive(x) = (x > 0) && !(x ≈ 0)
|
||||||
linspace(vmin, vmax, bins+1)
|
|
||||||
|
_positive_else_nan{T}(::Type{T}, x::Real) = _is_positive(x) ? T(x) : T(NaN)
|
||||||
|
|
||||||
|
function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, scale::Symbol)
|
||||||
|
if scale in _logScales
|
||||||
|
[_positive_else_nan(T, x) for x in V]
|
||||||
|
else
|
||||||
|
[T(x) for x in V]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# just pass through arrays
|
|
||||||
calc_edges(v, bins::AVec) = bins
|
|
||||||
|
|
||||||
# find the bucket index of this value
|
function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
|
||||||
function bucket_index(vi, edges)
|
if (scale in _logScales)
|
||||||
for (i,e) in enumerate(edges)
|
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
|
||||||
if vi <= e
|
else
|
||||||
return max(1,i-1)
|
zero(T)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
|
||||||
|
w_adj = _scale_adjusted_values(T, w, wscale)
|
||||||
|
w_min = minimum(w_adj)
|
||||||
|
w_max = maximum(w_adj)
|
||||||
|
baseline = _binbarlike_baseline(w_min, wscale)
|
||||||
|
w_adj, baseline
|
||||||
|
end
|
||||||
|
|
||||||
|
function _preprocess_barlike(d, x, y)
|
||||||
|
xscale = get(d, :xscale, :identity)
|
||||||
|
yscale = get(d, :yscale, :identity)
|
||||||
|
weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
|
||||||
|
x, weights, xscale, yscale, baseline
|
||||||
|
end
|
||||||
|
|
||||||
|
function _preprocess_binlike(d, x, y)
|
||||||
|
xscale = get(d, :xscale, :identity)
|
||||||
|
yscale = get(d, :yscale, :identity)
|
||||||
|
T = float(promote_type(eltype(x), eltype(y)))
|
||||||
|
edge = T.(x)
|
||||||
|
weights, baseline = _preprocess_binbarlike_weights(T, y, yscale)
|
||||||
|
edge, weights, xscale, yscale, baseline
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:barbins}}, x, y, z)
|
||||||
|
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
||||||
|
if (d[:bar_width] == nothing)
|
||||||
|
bar_width := diff(edge)
|
||||||
|
end
|
||||||
|
x := _bin_centers(edge)
|
||||||
|
y := weights
|
||||||
|
seriestype := :bar
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps barbins bar
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
||||||
|
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
||||||
|
xerror := diff(edge)/2
|
||||||
|
x := _bin_centers(edge)
|
||||||
|
y := weights
|
||||||
|
seriestype := :scatter
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps scatterbins scatter
|
||||||
|
|
||||||
|
|
||||||
|
function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol)
|
||||||
|
log_scale_x = xscale in _logScales
|
||||||
|
log_scale_y = yscale in _logScales
|
||||||
|
|
||||||
|
nbins = length(linearindices(weights))
|
||||||
|
if length(linearindices(edge)) != nbins + 1
|
||||||
|
error("Edge vector must be 1 longer than weight vector")
|
||||||
|
end
|
||||||
|
|
||||||
|
x = eltype(edge)[]
|
||||||
|
y = eltype(weights)[]
|
||||||
|
|
||||||
|
it_e, it_w = start(edge), start(weights)
|
||||||
|
a, it_e = next(edge, it_e)
|
||||||
|
last_w = eltype(weights)(NaN)
|
||||||
|
i = 1
|
||||||
|
while (!done(edge, it_e) && !done(edge, it_e))
|
||||||
|
b, it_e = next(edge, it_e)
|
||||||
|
w, it_w = next(weights, it_w)
|
||||||
|
|
||||||
|
if (log_scale_x && a ≈ 0)
|
||||||
|
a = b/_logScaleBases[xscale]^3
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if isnan(w)
|
||||||
|
if !isnan(last_w)
|
||||||
|
push!(x, a)
|
||||||
|
push!(y, baseline)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if isnan(last_w)
|
||||||
|
push!(x, a)
|
||||||
|
push!(y, baseline)
|
||||||
|
end
|
||||||
|
push!(x, a)
|
||||||
|
push!(y, w)
|
||||||
|
push!(x, b)
|
||||||
|
push!(y, w)
|
||||||
|
end
|
||||||
|
|
||||||
|
a = b
|
||||||
|
last_w = w
|
||||||
end
|
end
|
||||||
return length(edges)-1
|
if (last_w != baseline)
|
||||||
|
push!(x, a)
|
||||||
|
push!(y, baseline)
|
||||||
|
end
|
||||||
|
|
||||||
|
(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function my_hist(v, bins; normed = false, weights = nothing)
|
|
||||||
edges = calc_edges(v, bins)
|
|
||||||
counts = zeros(length(edges)-1)
|
|
||||||
|
|
||||||
# add a weighted count
|
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
|
||||||
for (i,vi) in enumerate(v)
|
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
|
||||||
idx = bucket_index(vi, edges)
|
|
||||||
counts[idx] += (weights == nothing ? 1.0 : weights[i])
|
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
||||||
|
|
||||||
|
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
|
||||||
|
if !isvertical(d)
|
||||||
|
xpts, ypts = ypts, xpts
|
||||||
end
|
end
|
||||||
|
|
||||||
# normalize by bar area?
|
# create a secondary series for the markers
|
||||||
norm_denom = normed ? sum(diff(edges) .* counts) : 1.0
|
if d[:markershape] != :none
|
||||||
if norm_denom == 0
|
@series begin
|
||||||
norm_denom = 1.0
|
seriestype := :scatter
|
||||||
|
x := _bin_centers(edge)
|
||||||
|
y := weights
|
||||||
|
fillrange := nothing
|
||||||
|
label := ""
|
||||||
|
primary := false
|
||||||
|
()
|
||||||
|
end
|
||||||
|
markershape := :none
|
||||||
|
xerror := :none
|
||||||
|
yerror := :none
|
||||||
end
|
end
|
||||||
|
|
||||||
edges, counts ./ norm_denom
|
x := xpts
|
||||||
|
y := ypts
|
||||||
|
seriestype := :path
|
||||||
|
()
|
||||||
|
end
|
||||||
|
Plots.@deps stepbins path
|
||||||
|
|
||||||
|
|
||||||
|
function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto)
|
||||||
|
_cl(x) = max(ceil(Int, x), 1)
|
||||||
|
_iqr(v) = quantile(v, 0.75) - quantile(v, 0.25)
|
||||||
|
_span(v) = maximum(v) - minimum(v)
|
||||||
|
|
||||||
|
n_samples = length(linearindices(first(vs)))
|
||||||
|
# Estimator for number of samples in one row/column of bins along each axis:
|
||||||
|
n = max(1, n_samples^(1/N))
|
||||||
|
|
||||||
|
v = vs[dim]
|
||||||
|
|
||||||
|
if mode == :auto
|
||||||
|
30
|
||||||
|
elseif mode == :sqrt # Square-root choice
|
||||||
|
_cl(sqrt(n))
|
||||||
|
elseif mode == :sturges # Sturges' formula
|
||||||
|
_cl(log2(n)) + 1
|
||||||
|
elseif mode == :rice # Rice Rule
|
||||||
|
_cl(2 * n^(1/3))
|
||||||
|
elseif mode == :scott # Scott's normal reference rule
|
||||||
|
_cl(_span(v) / (3.5 * std(v) / n^(1/3)))
|
||||||
|
elseif mode == :fd # Freedman–Diaconis rule
|
||||||
|
_cl(_span(v) / (2 * _iqr(v) / n^(1/3)))
|
||||||
|
else
|
||||||
|
error("Unknown auto-binning mode $mode")
|
||||||
|
end::Int
|
||||||
|
end
|
||||||
|
|
||||||
|
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left)
|
||||||
|
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning))
|
||||||
|
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) = binning
|
||||||
|
|
||||||
|
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::NTuple{N}) =
|
||||||
|
map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...))
|
||||||
|
|
||||||
|
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) =
|
||||||
|
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
|
||||||
|
|
||||||
|
_hist_norm_mode(mode::Symbol) = mode
|
||||||
|
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
|
||||||
|
|
||||||
|
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
|
||||||
|
info("binning = $binning")
|
||||||
|
edges = _hist_edges(vs, binning)
|
||||||
|
h = float( weights == nothing ?
|
||||||
|
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
|
||||||
|
StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left)
|
||||||
|
)
|
||||||
|
normalize!(h, mode = _hist_norm_mode(normed))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@recipe function f(::Type{Val{:histogram}}, x, y, z)
|
@recipe function f(::Type{Val{:histogram}}, x, y, z)
|
||||||
edges, counts = my_hist(y, d[:bins],
|
seriestype := :barhist
|
||||||
normed = d[:normalize],
|
|
||||||
weights = d[:weights])
|
|
||||||
x := edges
|
|
||||||
y := counts
|
|
||||||
seriestype := :bar
|
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
@deps histogram bar
|
@deps histogram barhist
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:barhist}}, x, y, z)
|
||||||
|
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
|
||||||
|
x := h.edges[1]
|
||||||
|
y := h.weights
|
||||||
|
seriestype := :barbins
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps barhist barbins
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:stephist}}, x, y, z)
|
||||||
|
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
|
||||||
|
x := h.edges[1]
|
||||||
|
y := h.weights
|
||||||
|
seriestype := :stepbins
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps stephist stepbins
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:scatterhist}}, x, y, z)
|
||||||
|
h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights])
|
||||||
|
x := h.edges[1]
|
||||||
|
y := h.weights
|
||||||
|
seriestype := :scatterbins
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps scatterhist scatterbins
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f{T, E}(h::StatsBase.Histogram{T, 1, E})
|
||||||
|
seriestype --> :barbins
|
||||||
|
|
||||||
|
st_map = Dict(
|
||||||
|
:bar => :barbins, :scatter => :scatterbins, :step => :stepbins,
|
||||||
|
:steppost => :stepbins # :step can be mapped to :steppost in pre-processing
|
||||||
|
)
|
||||||
|
seriestype := get(st_map, d[:seriestype], d[:seriestype])
|
||||||
|
|
||||||
|
if d[:seriestype] == :scatterbins
|
||||||
|
# Workaround, error bars currently not set correctly by scatterbins
|
||||||
|
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights)
|
||||||
|
xerror --> diff(h.edges[1])/2
|
||||||
|
seriestype := :scatter
|
||||||
|
(Plots._bin_centers(edge), weights)
|
||||||
|
else
|
||||||
|
(h.edges[1], h.weights)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f{H <: StatsBase.Histogram}(hv::AbstractVector{H})
|
||||||
|
for h in hv
|
||||||
|
@series begin
|
||||||
|
h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Histogram 2D
|
# Histogram 2D
|
||||||
|
|
||||||
# if tuple, map out bins, otherwise use the same for both
|
@recipe function f(::Type{Val{:bins2d}}, x, y, z)
|
||||||
calc_edges_2d(x, y, bins) = calc_edges(x, bins), calc_edges(y, bins)
|
edge_x, edge_y, weights = x, y, z.surf
|
||||||
calc_edges_2d{X,Y}(x, y, bins::Tuple{X,Y}) = calc_edges(x, bins[1]), calc_edges(y, bins[2])
|
|
||||||
|
|
||||||
# the 2D version
|
float_weights = float(weights)
|
||||||
function my_hist_2d(x, y, bins; normed = false, weights = nothing)
|
if is(float_weights, weights)
|
||||||
xedges, yedges = calc_edges_2d(x, y, bins)
|
float_weights = deepcopy(float_weights)
|
||||||
counts = zeros(length(yedges)-1, length(xedges)-1)
|
|
||||||
|
|
||||||
# add a weighted count
|
|
||||||
for i=1:length(x)
|
|
||||||
r = bucket_index(y[i], yedges)
|
|
||||||
c = bucket_index(x[i], xedges)
|
|
||||||
counts[r,c] += (weights == nothing ? 1.0 : weights[i])
|
|
||||||
end
|
end
|
||||||
|
for (i, c) in enumerate(float_weights)
|
||||||
# normalize to cubic area of the imaginary surface towers
|
|
||||||
norm_denom = normed ? sum((diff(yedges) * diff(xedges)') .* counts) : 1.0
|
|
||||||
if norm_denom == 0
|
|
||||||
norm_denom = 1.0
|
|
||||||
end
|
|
||||||
|
|
||||||
xedges, yedges, counts ./ norm_denom
|
|
||||||
end
|
|
||||||
|
|
||||||
centers(v::AVec) = 0.5 * (v[1:end-1] + v[2:end])
|
|
||||||
|
|
||||||
@recipe function f(::Type{Val{:histogram2d}}, x, y, z)
|
|
||||||
xedges, yedges, counts = my_hist_2d(x, y, d[:bins],
|
|
||||||
normed = d[:normalize],
|
|
||||||
weights = d[:weights])
|
|
||||||
for (i,c) in enumerate(counts)
|
|
||||||
if c == 0
|
if c == 0
|
||||||
counts[i] = NaN
|
float_weights[i] = NaN
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
x := centers(xedges)
|
|
||||||
y := centers(yedges)
|
x := Plots._bin_centers(edge_x)
|
||||||
z := Surface(counts)
|
y := Plots._bin_centers(edge_y)
|
||||||
linewidth := 0
|
z := Surface(float_weights)
|
||||||
|
|
||||||
|
match_dimensions := true
|
||||||
seriestype := :heatmap
|
seriestype := :heatmap
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
@deps histogram2d heatmap
|
Plots.@deps bins2d heatmap
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f(::Type{Val{:histogram2d}}, x, y, z)
|
||||||
|
h = _make_hist((x, y), d[:bins], normed = d[:normalize], weights = d[:weights])
|
||||||
|
x := h.edges[1]
|
||||||
|
y := h.edges[2]
|
||||||
|
z := Surface(h.weights)
|
||||||
|
seriestype := :bins2d
|
||||||
|
()
|
||||||
|
end
|
||||||
|
@deps histogram2d bins2d
|
||||||
|
|
||||||
|
|
||||||
|
@recipe function f{T, E}(h::StatsBase.Histogram{T, 2, E})
|
||||||
|
seriestype --> :bins2d
|
||||||
|
(h.edges[1], h.edges[2], Surface(h.weights))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@ -789,16 +1016,70 @@ abline!(args...; kw...) = abline!(current(), args...; kw...)
|
|||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Dates
|
# Dates
|
||||||
|
|
||||||
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int,dt), dt -> string(convert(Date,dt)))
|
dateformatter(dt) = string(convert(Date, dt))
|
||||||
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), dt -> string(convert(DateTime,dt)))
|
datetimeformatter(dt) = string(convert(DateTime, dt))
|
||||||
|
|
||||||
|
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, dt), dateformatter)
|
||||||
|
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int, dt), datetimeformatter)
|
||||||
|
|
||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Complex Numbers
|
# Complex Numbers
|
||||||
|
|
||||||
@userplot ComplexPlot
|
@recipe function f{T<:Number}(A::Array{Complex{T}})
|
||||||
@recipe function f(cp::ComplexPlot)
|
xguide --> "Re(x)"
|
||||||
xguide --> "Real Part"
|
yguide --> "Im(x)"
|
||||||
yguide --> "Imaginary Part"
|
real.(A), imag.(A)
|
||||||
seriestype --> :scatter
|
end
|
||||||
real(cp.args[1]), imag(cp.args[1])
|
|
||||||
|
# Splits a complex matrix to its real and complex parts
|
||||||
|
# Reals defaults solid, imaginary defaults dashed
|
||||||
|
# Label defaults are changed to match the real-imaginary reference / indexing
|
||||||
|
@recipe function f{T<:Real,T2}(x::AbstractArray{T},y::Array{Complex{T2}})
|
||||||
|
ylabel --> "Re(y)"
|
||||||
|
zlabel --> "Im(y)"
|
||||||
|
x,real.(y),imag.(y)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
# Color Gradients
|
||||||
|
|
||||||
|
@userplot ShowLibrary
|
||||||
|
@recipe function f(cl::ShowLibrary)
|
||||||
|
if !(length(cl.args) == 1 && isa(cl.args[1], Symbol))
|
||||||
|
error("showlibrary takes the name of a color library as a Symbol")
|
||||||
|
end
|
||||||
|
|
||||||
|
library = PlotUtils.color_libraries[cl.args[1]]
|
||||||
|
z = sqrt.((1:15)*(1:20)')
|
||||||
|
|
||||||
|
seriestype := :heatmap
|
||||||
|
ticks := nothing
|
||||||
|
legend := false
|
||||||
|
|
||||||
|
layout --> length(library.lib)
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for grad in sort(collect(keys(library.lib)))
|
||||||
|
@series begin
|
||||||
|
seriescolor := cgrad(grad, cl.args[1])
|
||||||
|
title := string(grad)
|
||||||
|
subplot := i += 1
|
||||||
|
z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@userplot ShowGradient
|
||||||
|
@recipe function f(grad::ShowGradient)
|
||||||
|
if !(length(grad.args) == 1 && isa(grad.args[1], Symbol))
|
||||||
|
error("showgradient takes the name of a color gradient as a Symbol")
|
||||||
|
end
|
||||||
|
z = sqrt.((1:15)*(1:20)')
|
||||||
|
seriestype := :heatmap
|
||||||
|
ticks := nothing
|
||||||
|
legend := false
|
||||||
|
seriescolor := grad.args[1]
|
||||||
|
title := string(grad.args[1])
|
||||||
|
z
|
||||||
end
|
end
|
||||||
|
|||||||
@ -39,7 +39,7 @@ series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot]
|
|||||||
function should_add_to_legend(series::Series)
|
function should_add_to_legend(series::Series)
|
||||||
series.d[:primary] && series.d[:label] != "" &&
|
series.d[:primary] && series.d[:label] != "" &&
|
||||||
!(series.d[:seriestype] in (
|
!(series.d[:seriestype] in (
|
||||||
:hexbin,:histogram2d,:hline,:vline,
|
:hexbin,:bins2d,:histogram2d,:hline,:vline,
|
||||||
:contour,:contourf,:contour3d,:surface,:wireframe,
|
:contour,:contourf,:contour3d,:surface,:wireframe,
|
||||||
:heatmap, :pie, :image
|
:heatmap, :pie, :image
|
||||||
))
|
))
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
function theme(s::Symbol; kw...)
|
function theme(s::Symbol; kw...)
|
||||||
# reset?
|
# reset?
|
||||||
if s == :none || s == :default
|
if s == :none || s == :default
|
||||||
PlotUtils._default_gradient[] = :inferno
|
PlotUtils.clibrary(:Plots)
|
||||||
|
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
|
||||||
default(;
|
default(;
|
||||||
bg = :white,
|
bg = :white,
|
||||||
bglegend = :match,
|
bglegend = :match,
|
||||||
@ -23,7 +24,8 @@ function theme(s::Symbol; kw...)
|
|||||||
# update the default gradient and other defaults
|
# update the default gradient and other defaults
|
||||||
thm = PlotThemes._themes[s]
|
thm = PlotThemes._themes[s]
|
||||||
if thm.gradient != nothing
|
if thm.gradient != nothing
|
||||||
PlotUtils._default_gradient[] = PlotThemes.gradient_name(s)
|
PlotUtils.clibrary(:misc)
|
||||||
|
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
|
||||||
end
|
end
|
||||||
default(;
|
default(;
|
||||||
bg = thm.bg_secondary,
|
bg = thm.bg_secondary,
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
# TODO: I declare lots of types here because of the lacking ability to do forward declarations in current Julia
|
# TODO: I declare lots of types here because of the lacking ability to do forward declarations in current Julia
|
||||||
# I should move these to the relevant files when something like "extern" is implemented
|
# I should move these to the relevant files when something like "extern" is implemented
|
||||||
|
|
||||||
typealias AVec AbstractVector
|
const AVec = AbstractVector
|
||||||
typealias AMat AbstractMatrix
|
const AMat = AbstractMatrix
|
||||||
typealias KW Dict{Symbol,Any}
|
const KW = Dict{Symbol,Any}
|
||||||
|
|
||||||
immutable PlotsDisplay <: Display end
|
immutable PlotsDisplay <: Display end
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ Extrema() = Extrema(Inf, -Inf)
|
|||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
typealias SubplotMap Dict{Any, Subplot}
|
const SubplotMap = Dict{Any, Subplot}
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,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.9.6"
|
const _current_plots_version = v"0.11.2"
|
||||||
|
|
||||||
|
|
||||||
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
|
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
|
||||||
|
|||||||
@ -23,7 +23,7 @@ facts("PyPlot") do
|
|||||||
@fact pyplot() --> Plots.PyPlotBackend()
|
@fact pyplot() --> Plots.PyPlotBackend()
|
||||||
@fact backend() --> Plots.PyPlotBackend()
|
@fact backend() --> Plots.PyPlotBackend()
|
||||||
|
|
||||||
image_comparison_facts(:pyplot, skip=[25,30], eps=img_eps)
|
image_comparison_facts(:pyplot, skip=[6,25,30], eps=img_eps)
|
||||||
end
|
end
|
||||||
|
|
||||||
facts("GR") do
|
facts("GR") do
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user