Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 226023043b | |||
| 5d2538c4c2 | |||
| b300e634f6 | |||
| 61d13b9b2d | |||
| 5ec80ad1f1 | |||
| 4849772435 | |||
| 6546879d3a | |||
| cbc379daa9 | |||
| a7be08ef46 | |||
| 47e48e5d27 | |||
| 968b8109dd | |||
| 19fba27951 | |||
| b78da20d04 | |||
| 5e445b4a71 | |||
| 0e5df883d0 | |||
| b79ea119ea | |||
| b21d98affd | |||
| d83666bed3 | |||
| cab6ca3ef0 | |||
| 33a37f9494 | |||
| 79e978aac9 | |||
| 3af60a81f8 | |||
| 56525ced92 | |||
| 581f3797bc | |||
| 2c8d51988b | |||
| 19243b741a | |||
| afc1e08f21 | |||
| 80c01e74c6 | |||
| d728bfb90c | |||
| 203d73ee26 | |||
| 05fe220102 | |||
| c4f2de198e | |||
| 50f9846836 | |||
| a33b3cfbd8 | |||
| 248f7cce90 | |||
| 8f381e2611 | |||
| f4b14d0d8d | |||
| 93428815e4 | |||
| 6b70610770 | |||
| 84eead47e3 | |||
| 009d03f1f8 | |||
| 9482a247e7 | |||
| 022c79fa95 | |||
| a9ed4ac21d | |||
| 354e39e9bf | |||
| 757e08c6fe | |||
| 33e5775294 | |||
| 5b73a8ed1c | |||
| f864ebbf1a | |||
| 54b6051315 | |||
| ebea34920b | |||
| 44294306ce | |||
| c2af1a0666 | |||
| 8f30696a4d | |||
| b58082a37b | |||
| a594878860 | |||
| 3a2b6296ac | |||
| 87af609a6f | |||
| a0d5d0f3c8 | |||
| 53510f3268 | |||
| 9d5ce9753a | |||
| d7a2df41fa | |||
| f905cb9577 | |||
| b9b6439f47 | |||
| ffcdf986a3 | |||
| 43245b5eb5 | |||
| 420228c67b | |||
| f1719d6e91 | |||
| 9aa1fd5c00 | |||
| 141845aa40 | |||
| 7867df6079 | |||
| 182b937143 | |||
| 5a54fb7e9f | |||
| 399a9b16f6 | |||
| fef45dfc30 | |||
| 42aa7d8d55 | |||
| 8778119792 | |||
| 10e3f2c990 | |||
| 5e25989366 | |||
| f12d328cf7 | |||
| efc4917724 | |||
| c2bf145ff5 | |||
| c8c82811b3 | |||
| c21e133e69 | |||
| 789a7fbb88 | |||
| 888ed9f0ae | |||
| 57da253fa8 | |||
| 44a6707397 | |||
| f0a3ca4314 | |||
| 9bbd52dcc2 | |||
| f50862ac51 | |||
| 017bed1a07 | |||
| 3765d5f549 | |||
| dd28159564 | |||
| 63cdf9f8e7 | |||
| e30889aa12 | |||
| b7caec1bfe | |||
| 660786b99c | |||
| b060576209 | |||
| 7b3826c2d5 | |||
| 51d4416b00 | |||
| cfe6103f48 | |||
| bee8230079 | |||
| 3d77c59c92 | |||
| 667ed161c0 | |||
| 979f9495f1 | |||
| d29a44efa7 | |||
| 7750003033 | |||
| e673339dc4 | |||
| b20b47f8eb | |||
| 689e437bac | |||
| e6bb17dc86 | |||
| 80a97b0f26 | |||
| ffea050bc2 | |||
| 8951526d0d | |||
| 3e799fbe21 | |||
| 53e27dbc38 | |||
| 268c2861c9 | |||
| 15739bc0ee | |||
| c2e8b5a1fa | |||
| 1a67ca897c | |||
| d1980ef978 | |||
| b3db49b4ae |
@@ -11,6 +11,51 @@
|
||||
---
|
||||
## (current master)
|
||||
|
||||
## 0.24.0
|
||||
- Update to the new PyCall and PyPlot API
|
||||
|
||||
## 0.23.2
|
||||
- pyplot fixes
|
||||
- Add option :tex_output_standalone to set the 'include_preamble' argument in the PGFPlots backend.
|
||||
- fix ticks
|
||||
- support plotly json mime
|
||||
- fix image axis limits
|
||||
- default to radius 0 at center for polar plots
|
||||
|
||||
## 0.23.1
|
||||
- slightly faster load time
|
||||
- fixed errant MethodError
|
||||
- fix bar plots with unicodeplots
|
||||
- better colorbars for contour
|
||||
- add volume seriestype for GR
|
||||
- fix passing a tuple to custom ticks
|
||||
- add vline to pgfplots
|
||||
- add tex output for pyplot
|
||||
- better 3d axis labels for GR
|
||||
|
||||
## 0.23.0
|
||||
- compatible with StatPlots -> StatsPlots name shift
|
||||
- fix histograms for vectors with NaN and Inf
|
||||
- change gif behaviour (remove cache-busting)
|
||||
- improved docstrings for shorthands functions
|
||||
- fix font rotation for pyplot
|
||||
- fix greyscale images for pyplot
|
||||
- clamp greyscale images with values outside 0,1
|
||||
- support keyword argument for font options
|
||||
- allow vector of markers for pyplot scatter
|
||||
|
||||
## 0.22.5
|
||||
- improve behaviour of plotlyjs backend
|
||||
|
||||
## 0.22.4
|
||||
- Add support for discrete contourf plots with GR
|
||||
|
||||
## 0.22.3
|
||||
- Fix the `showtheme` function
|
||||
|
||||
## 0.22.2
|
||||
- Allow annotations to accept a Tuple instead of the result of a text call (making it possible to specify font characteristics in recipes). E.g. `annotations = (2, 4, ("test", :right, 8, :red))` is the same as `annotations = (2, 4, text("test", :right, 8, :red))`
|
||||
|
||||
## 0.22.1
|
||||
- push PlotsDisplay just after REPLDisplay
|
||||
|
||||
@@ -182,7 +227,7 @@ Many updates, min julia 1.0
|
||||
- add `reset_defaults()` function to reset plot defaults
|
||||
- update syntax to 0.6
|
||||
- make `fill = true` fill to 0 rather than to 1
|
||||
- use new `@df` syntax in StatPlots examples
|
||||
- use new `@df` syntax in StatsPlots examples
|
||||
- allow changing the color of legend box
|
||||
- implement `title_location` for gr
|
||||
- add `hline` marker to pgfplots - fixes errorbars
|
||||
@@ -334,7 +379,7 @@ Many updates, min julia 1.0
|
||||
- added dependency on PlotThemes
|
||||
- set_theme --> theme
|
||||
- remove Compat from REQUIRE
|
||||
- warning for DataFrames without StatPlots
|
||||
- warning for DataFrames without StatsPlots
|
||||
- closeall exported and implemented for gr/pyplot
|
||||
- fix DateTime recipe
|
||||
- reset theme with theme(:none)
|
||||
@@ -456,8 +501,8 @@ Many updates, min julia 1.0
|
||||
#### 0.8.0
|
||||
|
||||
- added dependency on PlotUtils
|
||||
- BREAKING: removed DataFrames support (now in StatPlots.jl)
|
||||
- BREAKING: removed boxplot/violin/density recipes (now in StatPlots.jl)
|
||||
- BREAKING: removed DataFrames support (now in StatsPlots.jl)
|
||||
- BREAKING: removed boxplot/violin/density recipes (now in StatsPlots.jl)
|
||||
- GR:
|
||||
- inline iterm2 support
|
||||
- trisurface support
|
||||
|
||||
+4
-93
@@ -1,6 +1,6 @@
|
||||
module Plots
|
||||
|
||||
_current_plots_version = v"0.20.6"
|
||||
_current_plots_version = v"0.24.0"
|
||||
|
||||
using Reexport
|
||||
|
||||
@@ -84,7 +84,6 @@ export
|
||||
backends,
|
||||
backend_name,
|
||||
backend_object,
|
||||
add_backend,
|
||||
aliases,
|
||||
|
||||
Shape,
|
||||
@@ -180,103 +179,15 @@ include("arg_desc.jl")
|
||||
include("plotattr.jl")
|
||||
include("backends.jl")
|
||||
include("output.jl")
|
||||
include("ijulia.jl")
|
||||
include("fileio.jl")
|
||||
include("init.jl")
|
||||
|
||||
include("backends/plotly.jl")
|
||||
include("backends/gr.jl")
|
||||
include("backends/web.jl")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@shorthands scatter
|
||||
@shorthands bar
|
||||
@shorthands barh
|
||||
@shorthands histogram
|
||||
@shorthands barhist
|
||||
@shorthands stephist
|
||||
@shorthands scatterhist
|
||||
@shorthands histogram2d
|
||||
@shorthands density
|
||||
@shorthands heatmap
|
||||
@shorthands plots_heatmap
|
||||
@shorthands hexbin
|
||||
@shorthands sticks
|
||||
@shorthands hline
|
||||
@shorthands vline
|
||||
@shorthands hspan
|
||||
@shorthands vspan
|
||||
@shorthands ohlc
|
||||
@shorthands contour
|
||||
@shorthands contourf
|
||||
@shorthands contour3d
|
||||
@shorthands surface
|
||||
@shorthands wireframe
|
||||
@shorthands path3d
|
||||
@shorthands scatter3d
|
||||
@shorthands boxplot
|
||||
@shorthands violin
|
||||
@shorthands quiver
|
||||
@shorthands curves
|
||||
|
||||
"Plot a pie diagram"
|
||||
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
|
||||
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
|
||||
|
||||
"Plot with seriestype :path3d"
|
||||
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
|
||||
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
|
||||
|
||||
"Add title to an existing plot"
|
||||
title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
|
||||
|
||||
"Add xlabel to an existing plot"
|
||||
xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
|
||||
|
||||
"Add ylabel to an existing plot"
|
||||
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
|
||||
|
||||
"Set xlims for an existing plot"
|
||||
xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...)
|
||||
|
||||
"Set ylims for an existing plot"
|
||||
ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...)
|
||||
|
||||
"Set zlims for an existing plot"
|
||||
zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...)
|
||||
|
||||
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
|
||||
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
|
||||
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...)
|
||||
|
||||
|
||||
"Set xticks for an existing plot"
|
||||
xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
|
||||
|
||||
"Set yticks for an existing plot"
|
||||
yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
|
||||
|
||||
xticks!(
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
|
||||
yticks!(
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...)
|
||||
|
||||
"Add annotations to an existing plot"
|
||||
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
|
||||
annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...)
|
||||
|
||||
"Flip the current plots' x axis"
|
||||
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
|
||||
|
||||
"Flip the current plots' y axis"
|
||||
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
|
||||
|
||||
"Specify x axis attributes for an existing plot"
|
||||
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
|
||||
|
||||
"Specify x axis attributes for an existing plot"
|
||||
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
|
||||
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
|
||||
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
|
||||
include("shorthands.jl")
|
||||
|
||||
let PlotOrSubplot = Union{Plot, Subplot}
|
||||
global title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
|
||||
|
||||
+11
-3
@@ -93,19 +93,27 @@ end
|
||||
|
||||
|
||||
|
||||
# write out html to view the gif... note the rand call which is a hack so the image doesn't get cached
|
||||
# write out html to view the gif
|
||||
function Base.show(io::IO, ::MIME"text/html", agif::AnimatedGif)
|
||||
ext = file_extension(agif.filename)
|
||||
write(io, if ext == "gif"
|
||||
"<img src=\"$(relpath(agif.filename))?$(rand())>\" />"
|
||||
"<img src=\"$(relpath(agif.filename))\" />"
|
||||
elseif ext in ("mov", "mp4")
|
||||
"<video controls><source src=\"$(relpath(agif.filename))?$(rand())>\" type=\"video/$ext\"></video>"
|
||||
"<video controls><source src=\"$(relpath(agif.filename)) type=\"video/$ext\"></video>"
|
||||
else
|
||||
error("Cannot show animation with extension $ext: $agif")
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
# Only gifs can be shown via image/gif
|
||||
Base.showable(::MIME"image/gif", agif::AnimatedGif) = file_extension(agif.filename) == "gif"
|
||||
|
||||
function Base.show(io::IO, ::MIME"image/gif", agif::AnimatedGif)
|
||||
open(fio-> write(io, fio), agif.filename)
|
||||
end
|
||||
|
||||
|
||||
# -----------------------------------------------
|
||||
|
||||
function _animate(forloop::Expr, args...; callgif = false)
|
||||
|
||||
+25
-24
@@ -2,7 +2,7 @@
|
||||
const _arg_desc = KW(
|
||||
|
||||
# series args
|
||||
:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.",
|
||||
:label => "String type. The label for a series, which appears in a legend. If empty, no legend entry is added.",
|
||||
:seriescolor => "Color Type. The base color for this series. `:auto` (the default) will select a color from the subplot's `color_palette`, based on the order it was added to the subplot",
|
||||
:seriesalpha => "Number in [0,1]. The alpha/opacity override for the series. `nothing` (the default) means it will take the alpha value of the color.",
|
||||
:seriestype => "Symbol. This is the identifier of the type of visualization for this series. Choose from $(_allTypes) or any series recipes which are defined.",
|
||||
@@ -10,7 +10,7 @@ const _arg_desc = KW(
|
||||
:linewidth => "Number. Width of the line (in pixels)",
|
||||
:linecolor => "Color Type. Color of the line (for path and bar stroke). `:match` will take the value from `:seriescolor`, (though histogram/bar types use `:black` as a default).",
|
||||
:linealpha => "Number in [0,1]. The alpha/opacity override for the line. `nothing` (the default) means it will take the alpha value of linecolor.",
|
||||
:fillrange => "Number or AbstractVector. Fills area from this to y for line-types, sets the base for bar/stick types, and similar for other types.",
|
||||
:fillrange => "Number or AbstractVector. Fills area between fillrange and y for line-types, sets the base for bar/stick types, and similar for other types.",
|
||||
:fillcolor => "Color Type. Color of the filled area of path or bar types. `:match` will take the value from `:seriescolor`.",
|
||||
:fillalpha => "Number in [0,1]. The alpha/opacity override for the fill area. `nothing` (the default) means it will take the alpha value of fillcolor.",
|
||||
:markershape => "Symbol, Shape, or AbstractVector. Choose from $(_allMarkers).",
|
||||
@@ -21,7 +21,7 @@ const _arg_desc = KW(
|
||||
: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`.",
|
||||
: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 or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(min(x), stop = extrema(x), length = 25)`",
|
||||
:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto (the Freedman-Diaconis rule). For histogram-types, defines the approximate number of bins to aim for, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd). For fine-grained control pass a Vector of break values, e.g. `range(minimum(x), stop = maximum(x), length = 25)`",
|
||||
:smooth => "Bool. Add a regression line?",
|
||||
:group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.",
|
||||
:x => "Various. Input data. First Dimension",
|
||||
@@ -29,13 +29,13 @@ const _arg_desc = KW(
|
||||
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
|
||||
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
|
||||
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or Function `f(x,y) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
|
||||
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
|
||||
:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.",
|
||||
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
|
||||
:levels => "Integer, NTuple{2,Integer}, or AbstractVector. Levels or number of levels (or x-levels/y-levels) for a contour type.",
|
||||
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
|
||||
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
|
||||
:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).",
|
||||
:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?",
|
||||
:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)",
|
||||
:bar_width => "nothing or Number. Width of bars in data coordinates. When nothing, chooses based on x (or y when `orientation = :h`).",
|
||||
:bar_edges => "Bool. Align bars to edges (true), or centers (the default)?",
|
||||
:xerror => "AbstractVector or 2-Tuple of Vectors. x (horizontal) error relative to x-value. If 2-tuple of vectors, the first vector corresponds to the left error (and the second to the right)",
|
||||
:yerror => "AbstractVector or 2-Tuple of Vectors. y (vertical) error relative to y-value. If 2-tuple of vectors, the first vector corresponds to the bottom error (and the second to the top)",
|
||||
: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.",
|
||||
@@ -43,12 +43,12 @@ const _arg_desc = KW(
|
||||
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).",
|
||||
:weights => "AbstractVector. Used in histogram types for weighted counts.",
|
||||
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
|
||||
:contour_labels => "Bool. Show labels at the contour lines?",
|
||||
:contour_labels => "Bool. Show labels at the contour lines?",
|
||||
: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`.",
|
||||
:subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.",
|
||||
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",
|
||||
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
|
||||
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
|
||||
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",
|
||||
:primary => "Bool. Does this count as a 'real series'? For example, you could have a path (primary), and a scatter (secondary) as 2 separate series, maybe with different data (see sticks recipe for an example). The secondary series will get the same color, etc as the primary.",
|
||||
:hover => "nothing or vector of strings. Text to display when hovering over each data point.",
|
||||
|
||||
# plot args
|
||||
:plot_title => "String. Title for the whole plot (not the subplots) (Note: Not currently implemented)",
|
||||
@@ -63,11 +63,12 @@ const _arg_desc = KW(
|
||||
:link => "Symbol. How/whether to link axis limits between subplots. Values: `:none`, `:x` (x axes are linked by columns), `:y` (y axes are linked by rows), `:both` (x and y are linked), `:all` (every subplot is linked together regardless of layout position).",
|
||||
:overwrite_figure => "Bool. Should we reuse the same GUI window/figure when plotting (true) or open a new one (false).",
|
||||
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
|
||||
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
|
||||
:dpi => "Number. Dots Per Inch of output figures",
|
||||
:tex_output_standalone => "Bool. When writing tex output, should the source include a preamble for a standalone document class.",
|
||||
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
|
||||
:dpi => "Number. Dots Per Inch of output figures",
|
||||
:thickness_scaling => "Number. Scale for the thickness of all line elements like lines, borders, axes, grid lines, ... defaults to 1.",
|
||||
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
||||
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
||||
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
||||
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
||||
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
|
||||
|
||||
# subplot args
|
||||
@@ -98,7 +99,7 @@ const _arg_desc = KW(
|
||||
:legendfont => "Font. Font of legend items.",
|
||||
:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.",
|
||||
:projection => "Symbol or String. '3d' or 'polar'",
|
||||
:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `apect_ratio` x-units.",
|
||||
:aspect_ratio => "Symbol (:equal) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units.",
|
||||
:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.",
|
||||
:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.",
|
||||
:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.",
|
||||
@@ -110,14 +111,14 @@ const _arg_desc = KW(
|
||||
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots",
|
||||
|
||||
# axis args
|
||||
:guide => "String. Axis guide (label).",
|
||||
:guide => "String. Axis guide (label).",
|
||||
:guide_position => "Symbol. Position of axis guides: :top, :bottom, :left or :right",
|
||||
:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]",
|
||||
:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
|
||||
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
|
||||
:rotation => "Number. Degrees rotation of tick labels.",
|
||||
:flip => "Bool. Should we flip (reverse) the axis?",
|
||||
:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
|
||||
:lims => "NTuple{2,Number} or Symbol. Force axis limits. Only finite values are used (you can set only the right limit with `xlims = (-Inf, 2)` for example). `:round` widens the limit to the nearest round number ie. [0.1,3.6]=>[0.0,4.0]",
|
||||
:ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`",
|
||||
:scale => "Symbol. Scale of the axis: `:none`, `:ln`, `:log2`, `:log10`",
|
||||
:rotation => "Number. Degrees rotation of tick labels.",
|
||||
:flip => "Bool. Should we flip (reverse) the axis?",
|
||||
:formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.",
|
||||
:tickfontfamily => "String or Symbol. Font family of tick labels.",
|
||||
:tickfontsize => "Integer. Font pointsize of tick labels.",
|
||||
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
|
||||
|
||||
+3
-2
@@ -298,6 +298,7 @@ const _plot_defaults = KW(
|
||||
:link => :none,
|
||||
:overwrite_figure => true,
|
||||
:html_output_format => :auto,
|
||||
:tex_output_standalone => false,
|
||||
:inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are
|
||||
# the parent layout and the relative bounding box of inset subplots
|
||||
:dpi => DPI, # dots per inch for images, etc
|
||||
@@ -1050,8 +1051,8 @@ function preprocessArgs!(plotattributes::KW)
|
||||
|
||||
# warnings for moved recipes
|
||||
st = get(plotattributes, :seriestype, :path)
|
||||
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatPlots)
|
||||
@warn("seriestype $st has been moved to StatPlots. To use: \`Pkg.add(\"StatPlots\"); using StatPlots\`")
|
||||
if st in (:boxplot, :violin, :density) && !isdefined(Main, :StatsPlots)
|
||||
@warn("seriestype $st has been moved to StatsPlots. To use: \`Pkg.add(\"StatsPlots\"); using StatsPlots\`")
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
+10
-10
@@ -240,7 +240,7 @@ end
|
||||
# return (continuous_values, discrete_values) for the ticks on this axis
|
||||
function get_ticks(axis::Axis)
|
||||
ticks = _transform_ticks(axis[:ticks])
|
||||
ticks in (nothing, false) && return nothing
|
||||
ticks in (:none, nothing, false) && return nothing
|
||||
|
||||
# treat :native ticks as :auto
|
||||
ticks = ticks == :native ? :auto : ticks
|
||||
@@ -251,7 +251,7 @@ function get_ticks(axis::Axis)
|
||||
# discrete ticks...
|
||||
n = length(dvals)
|
||||
rng = if ticks == :auto
|
||||
Int[round(Int,i) for i in range(1, stop=n, length=15)]
|
||||
Int[round(Int,i) for i in range(1, stop=n, length=min(n,15))]
|
||||
else # if ticks == :all
|
||||
1:n
|
||||
end
|
||||
@@ -287,7 +287,7 @@ _transform_ticks(ticks::AbstractArray{T}) where T <: Dates.TimeType = Dates.valu
|
||||
_transform_ticks(ticks::NTuple{2, Any}) = (_transform_ticks(ticks[1]), ticks[2])
|
||||
|
||||
function get_minor_ticks(axis,ticks)
|
||||
axis[:minorticks] in (nothing, false) && !axis[:minorgrid] && return nothing
|
||||
axis[:minorticks] in (:none, nothing, false) && !axis[:minorgrid] && return nothing
|
||||
ticks = ticks[1]
|
||||
length(ticks) < 2 && return nothing
|
||||
|
||||
@@ -502,7 +502,7 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis)
|
||||
amin, amax = 0, 2pi
|
||||
elseif lims == :auto
|
||||
#widen max radius so ticks dont overlap with theta axis
|
||||
amin, amax + 0.1 * abs(amax - amin)
|
||||
0, amax + 0.1 * abs(amax - amin)
|
||||
else
|
||||
amin, amax
|
||||
end
|
||||
@@ -614,14 +614,14 @@ function axis_drawing_info(sp::Subplot)
|
||||
end
|
||||
push!(xaxis_segs, (xmin, y1), (xmax, y1))
|
||||
# don't show the 0 tick label for the origin framestyle
|
||||
if sp[:framestyle] == :origin && !(xticks in (nothing,false)) && length(xticks) > 1
|
||||
if sp[:framestyle] == :origin && !(xticks in (:none, nothing, false)) && length(xticks) > 1
|
||||
showticks = xticks[1] .!= 0
|
||||
xticks = (xticks[1][showticks], xticks[2][showticks])
|
||||
end
|
||||
end
|
||||
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine
|
||||
end
|
||||
if !(xaxis[:ticks] in (nothing, false))
|
||||
if !(xaxis[:ticks] in (:none, nothing, false))
|
||||
f = scalefunc(yaxis[:scale])
|
||||
invf = invscalefunc(yaxis[:scale])
|
||||
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
|
||||
@@ -642,7 +642,7 @@ function axis_drawing_info(sp::Subplot)
|
||||
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
|
||||
end
|
||||
end
|
||||
if !(xaxis[:minorticks] in (nothing, false)) || xaxis[:minorgrid]
|
||||
if !(xaxis[:minorticks] in (:none, nothing, false)) || xaxis[:minorgrid]
|
||||
f = scalefunc(yaxis[:scale])
|
||||
invf = invscalefunc(yaxis[:scale])
|
||||
ticks_in = xaxis[:tick_direction] == :out ? -1 : 1
|
||||
@@ -675,14 +675,14 @@ function axis_drawing_info(sp::Subplot)
|
||||
end
|
||||
push!(yaxis_segs, (x1, ymin), (x1, ymax))
|
||||
# don't show the 0 tick label for the origin framestyle
|
||||
if sp[:framestyle] == :origin && !(yticks in (nothing,false)) && length(yticks) > 1
|
||||
if sp[:framestyle] == :origin && !(yticks in (:none, nothing,false)) && length(yticks) > 1
|
||||
showticks = yticks[1] .!= 0
|
||||
yticks = (yticks[1][showticks], yticks[2][showticks])
|
||||
end
|
||||
end
|
||||
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine
|
||||
end
|
||||
if !(yaxis[:ticks] in (nothing, false))
|
||||
if !(yaxis[:ticks] in (:none, nothing, false))
|
||||
f = scalefunc(xaxis[:scale])
|
||||
invf = invscalefunc(xaxis[:scale])
|
||||
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
|
||||
@@ -703,7 +703,7 @@ function axis_drawing_info(sp::Subplot)
|
||||
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
|
||||
end
|
||||
end
|
||||
if !(yaxis[:minorticks] in (nothing, false)) || yaxis[:minorgrid]
|
||||
if !(yaxis[:minorticks] in (:none, nothing, false)) || yaxis[:minorgrid]
|
||||
f = scalefunc(xaxis[:scale])
|
||||
invf = invscalefunc(xaxis[:scale])
|
||||
ticks_in = yaxis[:tick_direction] == :out ? -1 : 1
|
||||
|
||||
+37
-98
@@ -7,16 +7,20 @@ const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
|
||||
const _backends = Symbol[]
|
||||
const _initialized_backends = Set{Symbol}()
|
||||
const _default_backends = (:none, :gr, :plotly)
|
||||
const _backendPackage = Dict{Symbol, Symbol}()
|
||||
|
||||
const _backend_packages = Dict{Symbol, Symbol}()
|
||||
|
||||
"Returns a list of supported backends"
|
||||
backends() = _backends
|
||||
|
||||
"Returns the name of the current backend"
|
||||
backend_name() = CURRENT_BACKEND.sym
|
||||
_backend_instance(sym::Symbol) = haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
|
||||
backend_package(pkg::Symbol) = pkg in _default_backends ? :Plots : Symbol("Plots", _backendPackage[pkg])
|
||||
backend_package_name(sym::Symbol) = sym in _default_backends ? :Plots : _backendPackage[sym]
|
||||
|
||||
function _backend_instance(sym::Symbol)::AbstractBackend
|
||||
haskey(_backendType, sym) ? _backendType[sym]() : error("Unsupported backend $sym")
|
||||
end
|
||||
|
||||
backend_package_name(sym::Symbol) = _backend_packages[sym]
|
||||
|
||||
macro init_backend(s)
|
||||
package_str = string(s)
|
||||
@@ -26,13 +30,13 @@ macro init_backend(s)
|
||||
esc(quote
|
||||
struct $T <: AbstractBackend end
|
||||
export $sym
|
||||
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
|
||||
$sym(; kw...) = (default(; kw...); backend($T()))
|
||||
backend_name(::$T) = Symbol($str)
|
||||
backend_package_name(pkg::$T) = backend_package_name(Symbol($str))
|
||||
push!(_backends, Symbol($str))
|
||||
_backendType[Symbol($str)] = $T
|
||||
_backendSymbol[$T] = Symbol($str)
|
||||
_backendPackage[Symbol($str)] = Symbol($package_str)
|
||||
_backend_packages[Symbol($str)] = Symbol($package_str)
|
||||
# include("backends/" * $str * ".jl")
|
||||
end)
|
||||
end
|
||||
@@ -42,12 +46,6 @@ end
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
function add_backend(pkg::Symbol)
|
||||
@info("To do a standard install of $pkg, copy and run this:\n\n")
|
||||
println(add_backend_string(_backend_instance(pkg)))
|
||||
println()
|
||||
end
|
||||
|
||||
# don't do anything as a default
|
||||
_create_backend_figure(plt::Plot) = nothing
|
||||
_prepare_plot_object(plt::Plot) = nothing
|
||||
@@ -138,33 +136,27 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, _backend_instance(sym))
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
function pickDefaultBackend()
|
||||
_fallback_default_backend() = backend(GRBackend())
|
||||
|
||||
function _pick_default_backend()
|
||||
env_default = get(ENV, "PLOTS_DEFAULT_BACKEND", "")
|
||||
if env_default != ""
|
||||
sym = Symbol(lowercase(env_default))
|
||||
if sym in _backends
|
||||
if sym in _initialized_backends
|
||||
return backend(sym)
|
||||
backend(sym)
|
||||
else
|
||||
@warn("You have set `PLOTS_DEFAULT_BACKEND=$env_default` but `$(backend_package_name(sym))` is not loaded.")
|
||||
_fallback_default_backend()
|
||||
end
|
||||
else
|
||||
@warn("You have set PLOTS_DEFAULT_BACKEND=$env_default but it is not a valid backend package. Choose from:\n\t" *
|
||||
join(sort(_backends), "\n\t"))
|
||||
_fallback_default_backend()
|
||||
end
|
||||
else
|
||||
_fallback_default_backend()
|
||||
end
|
||||
|
||||
# the ordering/inclusion of this package list is my semi-arbitrary guess at
|
||||
# which one someone will want to use if they have the package installed...accounting for
|
||||
# features, speed, and robustness
|
||||
# for pkgstr in ("GR", "PyPlot", "PlotlyJS", "PGFPlots", "UnicodePlots", "InspectDR")
|
||||
# if pkgstr in keys(Pkg.installed())
|
||||
# return backend(Symbol(lowercase(pkgstr)))
|
||||
# end
|
||||
# end
|
||||
|
||||
# the default if nothing else is installed
|
||||
backend(:gr)
|
||||
end
|
||||
|
||||
|
||||
@@ -174,13 +166,11 @@ end
|
||||
Returns the current plotting package name. Initializes package on first call.
|
||||
"""
|
||||
function backend()
|
||||
if CURRENT_BACKEND.sym == :none
|
||||
_pick_default_backend()
|
||||
end
|
||||
|
||||
global CURRENT_BACKEND
|
||||
if CURRENT_BACKEND.sym == :none
|
||||
pickDefaultBackend()
|
||||
end
|
||||
|
||||
CURRENT_BACKEND.pkg
|
||||
CURRENT_BACKEND.pkg
|
||||
end
|
||||
|
||||
"""
|
||||
@@ -188,20 +178,13 @@ Set the plot backend.
|
||||
"""
|
||||
function backend(pkg::AbstractBackend)
|
||||
sym = backend_name(pkg)
|
||||
if sym in _initialized_backends
|
||||
CURRENT_BACKEND.sym = backend_name(pkg)
|
||||
CURRENT_BACKEND.pkg = pkg
|
||||
else
|
||||
# try
|
||||
_initialize_backend(pkg)
|
||||
push!(_initialized_backends, sym)
|
||||
CURRENT_BACKEND.sym = backend_name(pkg)
|
||||
CURRENT_BACKEND.pkg = pkg
|
||||
# catch
|
||||
# add_backend(sym)
|
||||
# end
|
||||
if !(sym in _initialized_backends)
|
||||
_initialize_backend(pkg)
|
||||
push!(_initialized_backends, sym)
|
||||
end
|
||||
backend()
|
||||
CURRENT_BACKEND.sym = sym
|
||||
CURRENT_BACKEND.pkg = pkg
|
||||
pkg
|
||||
end
|
||||
|
||||
function backend(sym::Symbol)
|
||||
@@ -209,8 +192,8 @@ function backend(sym::Symbol)
|
||||
backend(_backend_instance(sym))
|
||||
else
|
||||
@warn("`:$sym` is not a supported backend.")
|
||||
backend()
|
||||
end
|
||||
backend()
|
||||
end
|
||||
|
||||
const _deprecated_backends = [:qwt, :winston, :bokeh, :gadfly, :immerse, :glvisualize]
|
||||
@@ -316,13 +299,10 @@ function _initialize_backend(pkg::AbstractBackend)
|
||||
end
|
||||
end
|
||||
|
||||
function add_backend_string(pkg::AbstractBackend)
|
||||
sym = backend_package_name(pkg)
|
||||
"""
|
||||
using Pkg
|
||||
Pkg.add("$sym")
|
||||
"""
|
||||
end
|
||||
_initialize_backend(pkg::GRBackend) = nothing
|
||||
|
||||
_initialize_backend(pkg::PlotlyBackend) = nothing
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# gr
|
||||
@@ -371,7 +351,7 @@ const _gr_attr = merge_with_base_supported([
|
||||
const _gr_seriestype = [
|
||||
:path, :scatter, :straightline,
|
||||
:heatmap, :pie, :image,
|
||||
:contour, :path3d, :scatter3d, :surface, :wireframe,
|
||||
:contour, :path3d, :scatter3d, :surface, :wireframe, :volume,
|
||||
:shape
|
||||
]
|
||||
const _gr_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
@@ -379,13 +359,6 @@ const _gr_marker = _allMarkers
|
||||
const _gr_scale = [:identity, :log10]
|
||||
is_marker_supported(::GRBackend, shape::Shape) = true
|
||||
|
||||
function add_backend_string(::GRBackend)
|
||||
"""
|
||||
Pkg.add("GR")
|
||||
Pkg.build("GR")
|
||||
"""
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# plotly
|
||||
|
||||
@@ -444,17 +417,11 @@ const _plotly_marker = [
|
||||
]
|
||||
const _plotly_scale = [:identity, :log10]
|
||||
|
||||
defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# pgfplots
|
||||
|
||||
function add_backend_string(::PGFPlotsBackend)
|
||||
"""
|
||||
using Pkg
|
||||
Pkg.add("PGFPlots")
|
||||
Pkg.build("PGFPlots")
|
||||
"""
|
||||
end
|
||||
|
||||
const _pgfplots_attr = merge_with_base_supported([
|
||||
:annotations,
|
||||
:background_color_legend,
|
||||
@@ -492,29 +459,19 @@ const _pgfplots_attr = merge_with_base_supported([
|
||||
])
|
||||
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape, :straightline,]
|
||||
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
|
||||
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline, :vline] #vcat(_allMarkers, Shape)
|
||||
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# plotlyjs
|
||||
|
||||
function _initialize_backend(pkg::PlotlyJSBackend)
|
||||
sym = backend_package_name(pkg)
|
||||
@eval Main begin
|
||||
import PlotlyJS, ORCA
|
||||
export PlotlyJS
|
||||
end
|
||||
end
|
||||
|
||||
function add_backend_string(::PlotlyJSBackend)
|
||||
"""
|
||||
using Pkg
|
||||
Pkg.add(["PlotlyJS", "Blink", "ORCA"])
|
||||
import Blink
|
||||
Blink.AtomShell.install()
|
||||
"""
|
||||
end
|
||||
|
||||
const _plotlyjs_attr = _plotly_attr
|
||||
const _plotlyjs_seriestype = _plotly_seriestype
|
||||
const _plotlyjs_style = _plotly_style
|
||||
@@ -535,16 +492,6 @@ function _initialize_backend(::PyPlotBackend)
|
||||
end
|
||||
end
|
||||
|
||||
function add_backend_string(::PyPlotBackend)
|
||||
"""
|
||||
using Pkg
|
||||
withenv("PYTHON" => "") do
|
||||
Pkg.add("PyPlot")
|
||||
Pkg.build("PyPlot")
|
||||
end
|
||||
"""
|
||||
end
|
||||
|
||||
const _pyplot_attr = merge_with_base_supported([
|
||||
:annotations,
|
||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||
@@ -598,14 +545,6 @@ const _pyplot_scale = [:identity, :ln, :log2, :log10]
|
||||
# ------------------------------------------------------------------------------
|
||||
# unicodeplots
|
||||
|
||||
function add_backend_string(::UnicodePlotsBackend)
|
||||
"""
|
||||
using Pkg
|
||||
Pkg.add("UnicodePlots")
|
||||
Pkg.build("UnicodePlots")
|
||||
"""
|
||||
end
|
||||
|
||||
const _unicodeplots_attr = merge_with_base_supported([
|
||||
:label,
|
||||
:legend,
|
||||
|
||||
+90
-76
@@ -6,6 +6,7 @@
|
||||
import GR
|
||||
export GR
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
const gr_linetype = KW(
|
||||
@@ -235,6 +236,7 @@ end
|
||||
function gr_fill_viewport(vp::AVec{Float64}, c)
|
||||
GR.savestate()
|
||||
GR.selntran(0)
|
||||
GR.setscale(0)
|
||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||
gr_set_fillcolor(c)
|
||||
GR.fillrect(vp...)
|
||||
@@ -414,16 +416,24 @@ function gr_set_viewport_polar()
|
||||
end
|
||||
|
||||
# add the colorbar
|
||||
function gr_colorbar(sp::Subplot, clims)
|
||||
function gr_colorbar(sp::Subplot, clims, levels)
|
||||
GR.savestate()
|
||||
xmin, xmax = gr_xy_axislims(sp)[1:2]
|
||||
zmin, zmax = clims[1:2]
|
||||
gr_set_viewport_cmap(sp)
|
||||
l = zeros(Int32, 1, 256)
|
||||
l[1,:] = Int[round(Int, _i) for _i in range(1000, stop=1255, length=256)]
|
||||
l = if levels === nothing
|
||||
(1000:1255)'
|
||||
elseif length(levels) > 1
|
||||
min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels)
|
||||
round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255)
|
||||
else
|
||||
Int32[1000, 1255]
|
||||
end
|
||||
GR.setscale(0)
|
||||
GR.setwindow(xmin, xmax, clims[1], clims[2])
|
||||
GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l)
|
||||
ztick = 0.5 * GR.tick(clims[1], clims[2])
|
||||
GR.axes(0, ztick, xmax, clims[1], 0, 1, 0.005)
|
||||
GR.setwindow(xmin, xmax, zmin, zmax)
|
||||
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
|
||||
ztick = 0.5 * GR.tick(zmin, zmax)
|
||||
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
|
||||
|
||||
gr_set_font(guidefont(sp[:yaxis]))
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
@@ -431,7 +441,7 @@ function gr_colorbar(sp::Subplot, clims)
|
||||
gr_text(viewport_plotarea[2] + gr_colorbar_ratio,
|
||||
gr_view_ycenter(), sp[:colorbar_title])
|
||||
|
||||
gr_set_viewport_plotarea()
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2])
|
||||
@@ -470,7 +480,7 @@ end
|
||||
const _gr_gradient_alpha = ones(256)
|
||||
|
||||
function gr_set_gradient(c)
|
||||
grad = isa(c, ColorGradient) ? c : cgrad()
|
||||
grad = c isa ColorGradient ? c : cgrad()
|
||||
for (i,z) in enumerate(range(0, stop=1, length=256))
|
||||
c = grad[z]
|
||||
GR.setcolorrep(999+i, red(c), green(c), blue(c))
|
||||
@@ -659,7 +669,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# reduced from before... set some flags based on the series in this subplot
|
||||
# TODO: can these be generic flags?
|
||||
outside_ticks = false
|
||||
cmap = hascolorbar(sp)
|
||||
# calculate the colorbar limits once for a subplot
|
||||
clims = get_clims(sp)
|
||||
clevels = nothing
|
||||
|
||||
draw_axes = sp[:framestyle] != :none
|
||||
# axes_2d = true
|
||||
for series in series_list(sp)
|
||||
@@ -681,6 +694,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
expand_extrema!(sp[:yaxis], y)
|
||||
data_lims = gr_xy_axislims(sp)
|
||||
end
|
||||
|
||||
# color levels overwritten by the last relevant series
|
||||
hascolorbar(series) && (clevels = colorbar_levels(series, clims))
|
||||
end
|
||||
|
||||
# set our plot area view
|
||||
@@ -729,11 +745,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.setlinewidth(sp.plt[:thickness_scaling])
|
||||
|
||||
if is3d(sp)
|
||||
# TODO do we really need a different clims computation here from the one
|
||||
# computed above using get_clims(sp)?
|
||||
zmin, zmax = gr_lims(zaxis, true)
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
clims3d = sp[:clims]
|
||||
if is_2tuple(clims3d)
|
||||
isfinite(clims3d[1]) && (zmin = clims3d[1])
|
||||
isfinite(clims3d[2]) && (zmax = clims3d[2])
|
||||
end
|
||||
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...)
|
||||
xtick = GR.tick(xmin, xmax) / 2
|
||||
@@ -908,27 +926,39 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(xpos, viewport_subplot[4], sp[:title])
|
||||
end
|
||||
|
||||
if xaxis[:guide] != ""
|
||||
if is3d(sp)
|
||||
gr_set_font(guidefont(xaxis))
|
||||
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
||||
GR.titles3d(xaxis[:guide], yaxis[:guide], zaxis[:guide])
|
||||
else
|
||||
if xaxis[:guide] != ""
|
||||
gr_set_font(guidefont(xaxis))
|
||||
if xaxis[:guide_position] == :top || (xaxis[:guide_position] == :auto && xaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[4], xaxis[:guide])
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if yaxis[:guide] != ""
|
||||
gr_set_font(guidefont(yaxis))
|
||||
GR.setcharup(-1, 0)
|
||||
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
||||
if yaxis[:guide] != ""
|
||||
gr_set_font(guidefont(yaxis))
|
||||
GR.setcharup(-1, 0)
|
||||
if yaxis[:guide_position] == :right || (yaxis[:guide_position] == :auto && yaxis[:mirror] == true)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
if viewport_plotarea[1] - viewport_subplot[1] > 0.1
|
||||
gr_text(viewport_plotarea[2] + 0.025, gr_view_ycenter(), yaxis[:guide])
|
||||
else
|
||||
gr_text(viewport_subplot[2], gr_view_ycenter(), yaxis[:guide])
|
||||
end
|
||||
else
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
if viewport_plotarea[1] - viewport_subplot[1] > 0.1
|
||||
gr_text(viewport_plotarea[1] - 0.075, gr_view_ycenter(), yaxis[:guide])
|
||||
else
|
||||
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
GR.restorestate()
|
||||
@@ -938,15 +968,15 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
# this needs to be here to point the colormap to the right indices
|
||||
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
||||
|
||||
# calculate the colorbar limits once for a subplot
|
||||
clims = get_clims(sp)
|
||||
|
||||
for (idx, series) in enumerate(series_list(sp))
|
||||
st = series[:seriestype]
|
||||
|
||||
# update the current stored gradient
|
||||
if st in (:contour, :surface, :wireframe, :heatmap)
|
||||
if st in (:surface, :heatmap) ||
|
||||
(st == :contour && series[:fillrange] !== nothing)
|
||||
gr_set_gradient(series[:fillcolor]) #, series[:fillalpha])
|
||||
elseif st in (:contour, :wireframe)
|
||||
gr_set_gradient(series[:linecolor])
|
||||
elseif series[:marker_z] != nothing
|
||||
series[:markercolor] = gr_set_gradient(series[:markercolor])
|
||||
elseif series[:line_z] != nothing
|
||||
@@ -1022,35 +1052,21 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
|
||||
elseif st == :contour
|
||||
zmin, zmax = clims
|
||||
GR.setspace(zmin, zmax, 0, 90)
|
||||
if typeof(series[:levels]) <: AbstractArray
|
||||
h = series[:levels]
|
||||
else
|
||||
h = series[:levels] > 1 ? range(zmin, stop=zmax, length=series[:levels]) : [(zmin + zmax) / 2]
|
||||
GR.setspace(clims[1], clims[2], 0, 90)
|
||||
h = colorbar_levels(series, clims)
|
||||
GR.setlinetype(gr_linetype[get_linestyle(series)])
|
||||
GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001)))
|
||||
is_lc_black = let black=plot_color(:black)
|
||||
plot_color(series[:linecolor]) in (black,[black])
|
||||
end
|
||||
if series[:fillrange] != nothing
|
||||
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
||||
else
|
||||
GR.setlinetype(gr_linetype[get_linestyle(series)])
|
||||
GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001)))
|
||||
if plot_color(series[:linecolor]) == [plot_color(:black)]
|
||||
GR.contour(x, y, h, z, 0 + (series[:contour_labels] == true ? 1 : 0))
|
||||
else
|
||||
GR.contour(x, y, h, z, 1000 + (series[:contour_labels] == true ? 1 : 0))
|
||||
if series[:fillcolor] != series[:linecolor] && !is_lc_black
|
||||
@warn("GR: filled contour only supported with black contour lines")
|
||||
end
|
||||
end
|
||||
|
||||
# create the colorbar of contour levels
|
||||
if cmap
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||
gr_set_viewport_cmap(sp)
|
||||
l = (length(h) > 1) ? round.(Int32, 1000 .+ (h .- ignorenan_minimum(h)) ./ (ignorenan_maximum(h) - ignorenan_minimum(h)) .* 255) : Int32[1000, 1255]
|
||||
GR.setwindow(xmin, xmax, zmin, zmax)
|
||||
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
|
||||
ztick = 0.5 * GR.tick(zmin, zmax)
|
||||
GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005)
|
||||
gr_set_viewport_plotarea()
|
||||
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
|
||||
else
|
||||
coff = is_lc_black ? 0 : 1000
|
||||
GR.contour(x, y, h, z, coff + (series[:contour_labels] == true ? 1 : 0))
|
||||
end
|
||||
|
||||
elseif st in [:surface, :wireframe]
|
||||
@@ -1069,6 +1085,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
|
||||
end
|
||||
|
||||
elseif st == :volume
|
||||
sp[:legend] = :none
|
||||
GR.gr3.clear()
|
||||
dmin, dmax = GR.gr3.volume(y.v, 0)
|
||||
|
||||
elseif st == :heatmap
|
||||
xmin, xmax, ymin, ymax = xy_lims
|
||||
zmin, zmax = clims
|
||||
@@ -1179,19 +1200,19 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
elseif st == :image
|
||||
z = transpose_z(series, series[:z].surf, true)'
|
||||
w, h = length(x), length(y)
|
||||
w, h = size(z)
|
||||
xinds = sort(1:w, rev = xaxis[:flip])
|
||||
yinds = sort(1:h, rev = yaxis[:flip])
|
||||
z = z[xinds, yinds]
|
||||
xmin, xmax = ignorenan_extrema(series[:x]); ymin, ymax = ignorenan_extrema(series[:y])
|
||||
if eltype(z) <: Colors.AbstractGray
|
||||
grey = round.(UInt8, float(z) * 255)
|
||||
grey = round.(UInt8, clamp.(float(z) * 255, 0, 255))
|
||||
rgba = map(c -> UInt32( 0xff000000 + UInt(c)<<16 + UInt(c)<<8 + UInt(c) ), grey)
|
||||
else
|
||||
rgba = map(c -> UInt32( round(UInt, alpha(c) * 255) << 24 +
|
||||
round(UInt, blue(c) * 255) << 16 +
|
||||
round(UInt, green(c) * 255) << 8 +
|
||||
round(UInt, red(c) * 255) ), z)
|
||||
rgba = map(c -> UInt32( round(UInt, clamp(alpha(c) * 255, 0, 255)) << 24 +
|
||||
round(UInt, clamp(blue(c) * 255, 0, 255)) << 16 +
|
||||
round(UInt, clamp(green(c) * 255, 0, 255)) << 8 +
|
||||
round(UInt, clamp(red(c) * 255, 0, 255)) ), z)
|
||||
end
|
||||
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
|
||||
end
|
||||
@@ -1207,14 +1228,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
|
||||
# draw the colorbar
|
||||
GR.savestate()
|
||||
# special colorbar with steps is drawn for contours
|
||||
if cmap && any(series[:seriestype] != :contour for series in series_list(sp))
|
||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||
gr_set_transparency(1)
|
||||
gr_colorbar(sp, clims)
|
||||
end
|
||||
GR.restorestate()
|
||||
hascolorbar(sp) && gr_colorbar(sp, clims, clevels)
|
||||
|
||||
# add the legend
|
||||
if sp[:legend] != :none
|
||||
|
||||
@@ -26,7 +26,8 @@ const _pgfplots_markers = KW(
|
||||
:star6 => "asterisk",
|
||||
:diamond => "diamond*",
|
||||
:pentagon => "pentagon*",
|
||||
:hline => "-"
|
||||
:hline => "-",
|
||||
:vline => "|"
|
||||
)
|
||||
|
||||
const _pgfplots_legend_pos = KW(
|
||||
@@ -563,7 +564,7 @@ end
|
||||
|
||||
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
|
||||
fn = tempname()*".tex"
|
||||
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
|
||||
PGFPlots.save(fn, backend_object(plt), include_preamble=plt.attr[:tex_output_standalone])
|
||||
write(io, read(open(fn), String))
|
||||
end
|
||||
|
||||
|
||||
+12
-8
@@ -186,11 +186,6 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
|
||||
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
|
||||
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
|
||||
|
||||
# flip
|
||||
if axis[:flip]
|
||||
ax[:range] = reverse(ax[:range])
|
||||
end
|
||||
|
||||
# ticks
|
||||
if axis[:ticks] != :native
|
||||
ticks = get_ticks(axis)
|
||||
@@ -208,6 +203,10 @@ function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
|
||||
ax[:showgrid] = false
|
||||
end
|
||||
|
||||
# flip
|
||||
if axis[:flip]
|
||||
ax[:range] = reverse(ax[:range])
|
||||
end
|
||||
|
||||
ax
|
||||
end
|
||||
@@ -854,11 +853,16 @@ end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
|
||||
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyBackend})
|
||||
write(io, html_head(plt) * html_body(plt))
|
||||
function _show(io::IO, ::MIME"application/vnd.plotly.v1+json", plot::Plot{PlotlyBackend})
|
||||
data = []
|
||||
for series in plot.series_list
|
||||
append!(data, plotly_series(plot, series))
|
||||
end
|
||||
layout = plotly_layout(plot)
|
||||
JSON.print(io, Dict(:data => data, :layout => layout))
|
||||
end
|
||||
|
||||
|
||||
function _display(plt::Plot{PlotlyBackend})
|
||||
standalone_html_window(plt)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
# https://github.com/spencerlyon2/PlotlyJS.jl
|
||||
# https://github.com/sglyon/PlotlyJS.jl
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
@@ -50,23 +49,16 @@ end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
function _show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend})
|
||||
if isijulia() && !_use_remote[]
|
||||
write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o)))
|
||||
else
|
||||
show(io, MIME("text/html"), plt.o)
|
||||
end
|
||||
_show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend}) = show(io, MIME("text/html"), plt.o)
|
||||
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="svg")
|
||||
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="png")
|
||||
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="pdf")
|
||||
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = PlotlyJS.savefig(io, plt.o, format="eps")
|
||||
|
||||
function _show(io::IO, m::MIME"application/vnd.plotly.v1+json", plt::Plot{PlotlyJSBackend})
|
||||
show(io, m, plt.o)
|
||||
end
|
||||
|
||||
function plotlyjs_save_hack(io::IO, plt::Plot{PlotlyJSBackend}, ext::String)
|
||||
tmpfn = tempname() * "." * ext
|
||||
PlotlyJS.savefig(plt.o, tmpfn)
|
||||
write(io, read(open(tmpfn)))
|
||||
end
|
||||
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "svg")
|
||||
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png")
|
||||
_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")
|
||||
|
||||
function write_temp_html(plt::Plot{PlotlyJSBackend})
|
||||
filename = string(tempname(), ".html")
|
||||
|
||||
+201
-135
@@ -21,7 +21,7 @@ pyfont = PyPlot.pyimport("matplotlib.font_manager")
|
||||
pyticker = PyPlot.pyimport("matplotlib.ticker")
|
||||
pycmap = PyPlot.pyimport("matplotlib.cm")
|
||||
pynp = PyPlot.pyimport("numpy")
|
||||
pynp["seterr"](invalid="ignore")
|
||||
pynp."seterr"(invalid="ignore")
|
||||
pytransforms = PyPlot.pyimport("matplotlib.transforms")
|
||||
pycollections = PyPlot.pyimport("matplotlib.collections")
|
||||
pyart3d = PyPlot.art3D
|
||||
@@ -34,6 +34,11 @@ else
|
||||
:set_facecolor
|
||||
end
|
||||
|
||||
# PyCall API changes in v1.90.0
|
||||
if !isdefined(PyCall, :_setproperty!)
|
||||
@warn "Plots no longer supports PyCall < 1.90.0 and PyPlot < 2.8.0. Either update PyCall and PyPlot or pin Plots to a version <= 0.23.2."
|
||||
end
|
||||
|
||||
|
||||
# # convert colorant to 4-tuple RGBA
|
||||
# py_color(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha))
|
||||
@@ -64,8 +69,8 @@ py_color(c::Colorant, α) = py_color(plot_color(c, α))
|
||||
|
||||
function py_colormap(grad::ColorGradient)
|
||||
pyvals = [(z, py_color(grad[z])) for z in grad.values]
|
||||
cm = pycolors["LinearSegmentedColormap"][:from_list]("tmp", pyvals)
|
||||
cm[:set_bad](color=(0,0,0,0.0), alpha=0.0)
|
||||
cm = pycolors."LinearSegmentedColormap"."from_list"("tmp", pyvals)
|
||||
cm."set_bad"(color=(0,0,0,0.0), alpha=0.0)
|
||||
cm
|
||||
end
|
||||
py_colormap(c) = py_colormap(cgrad())
|
||||
@@ -73,8 +78,8 @@ py_colormap(c) = py_colormap(cgrad())
|
||||
|
||||
function py_shading(c, z)
|
||||
cmap = py_colormap(c)
|
||||
ls = pycolors["LightSource"](270,45)
|
||||
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
|
||||
ls = pycolors."LightSource"(270,45)
|
||||
ls."shade"(z, cmap, vert_exag=0.1, blend_mode="soft")
|
||||
end
|
||||
|
||||
# get the style (solid, dashed, etc)
|
||||
@@ -97,7 +102,7 @@ function py_marker(marker::Shape)
|
||||
mat[i,2] = y[i]
|
||||
end
|
||||
mat[n+1,:] = mat[1,:]
|
||||
pypath["Path"](mat)
|
||||
pypath."Path"(mat)
|
||||
end
|
||||
|
||||
const _path_MOVETO = UInt8(1)
|
||||
@@ -182,7 +187,7 @@ end
|
||||
# end
|
||||
|
||||
function get_locator_and_formatter(vals::AVec)
|
||||
pyticker["FixedLocator"](1:length(vals)), pyticker["FixedFormatter"](vals)
|
||||
pyticker."FixedLocator"(1:length(vals)), pyticker."FixedFormatter"(vals)
|
||||
end
|
||||
|
||||
function add_pyfixedformatter(cbar, vals::AVec)
|
||||
@@ -204,7 +209,7 @@ end
|
||||
|
||||
function py_mask_nans(z)
|
||||
# pynp["ma"][:masked_invalid](z)))
|
||||
PyCall.pycall(pynp["ma"][:masked_invalid], Any, z)
|
||||
PyCall.pycall(pynp."ma"."masked_invalid", Any, z)
|
||||
# pynp["ma"][:masked_where](pynp["isnan"](z),z)
|
||||
end
|
||||
|
||||
@@ -248,22 +253,22 @@ py_fillcolormap(series::Series) = py_colormap(series[:fillcolor])
|
||||
# Figure utils -- F*** matplotlib for making me work so hard to figure this crap out
|
||||
|
||||
# the drawing surface
|
||||
py_canvas(fig) = fig[:canvas]
|
||||
py_canvas(fig) = fig."canvas"
|
||||
|
||||
# the object controlling draw commands
|
||||
py_renderer(fig) = py_canvas(fig)[:get_renderer]()
|
||||
py_renderer(fig) = py_canvas(fig)."get_renderer"()
|
||||
|
||||
# draw commands... paint the screen (probably updating internals too)
|
||||
py_drawfig(fig) = fig[:draw](py_renderer(fig))
|
||||
py_drawfig(fig) = fig."draw"(py_renderer(fig))
|
||||
# py_drawax(ax) = ax[:draw](py_renderer(ax[:get_figure]()))
|
||||
|
||||
# get a vector [left, right, bottom, top] in PyPlot coords (origin is bottom-left!)
|
||||
py_extents(obj) = obj[:get_window_extent]()[:get_points]()
|
||||
py_extents(obj) = obj."get_window_extent"()."get_points"()
|
||||
|
||||
|
||||
# compute a bounding box (with origin top-left), however pyplot gives coords with origin bottom-left
|
||||
function py_bbox(obj)
|
||||
fl, fr, fb, ft = py_extents(obj[:get_figure]())
|
||||
fl, fr, fb, ft = py_extents(obj."get_figure"())
|
||||
l, r, b, t = py_extents(obj)
|
||||
BoundingBox(l*px, (ft-t)*px, (r-l)*px, (t-b)*px)
|
||||
end
|
||||
@@ -279,13 +284,13 @@ end
|
||||
|
||||
# bounding box: union of axis tick labels
|
||||
function py_bbox_ticks(ax, letter)
|
||||
labels = ax[Symbol("get_"*letter*"ticklabels")]()
|
||||
labels = getproperty(ax, Symbol("get_"*letter*"ticklabels"))()
|
||||
py_bbox(labels)
|
||||
end
|
||||
|
||||
# bounding box: axis guide
|
||||
function py_bbox_axislabel(ax, letter)
|
||||
pyaxis_label = ax[Symbol("get_"*letter*"axis")]()[:label]
|
||||
pyaxis_label = getproperty(ax, Symbol("get_"*letter*"axis"))().label
|
||||
py_bbox(pyaxis_label)
|
||||
end
|
||||
|
||||
@@ -301,7 +306,7 @@ end
|
||||
function py_bbox_title(ax)
|
||||
bb = defaultbox
|
||||
for s in (:title, :_left_title, :_right_title)
|
||||
bb = bb + py_bbox(ax[s])
|
||||
bb = bb + py_bbox(getproperty(ax, s))
|
||||
end
|
||||
bb
|
||||
end
|
||||
@@ -339,7 +344,7 @@ function py_init_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
|
||||
proj = (proj in (nothing,:none) ? nothing : string(proj))
|
||||
|
||||
# add a new axis, and force it to create a new one by setting a distinct label
|
||||
ax = fig[:add_axes](
|
||||
ax = fig."add_axes"(
|
||||
[0,0,1,1],
|
||||
label = string(gensym()),
|
||||
projection = proj
|
||||
@@ -440,7 +445,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# push!(handles, handle)
|
||||
# else
|
||||
for (i, rng) in enumerate(iter_segments(series))
|
||||
handle = ax[:plot]((arg[rng] for arg in xyargs)...;
|
||||
handle = ax."plot"((arg[rng] for arg in xyargs)...;
|
||||
label = i == 1 ? series[:label] : "",
|
||||
zorder = series[:series_plotindex],
|
||||
color = py_color(get_linecolor(series, clims, i), get_linealpha(series, i)),
|
||||
@@ -468,7 +473,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
:linestyle => py_linestyle(st, get_linestyle(series)),
|
||||
)
|
||||
add_arrows(x, y) do xyprev, xy
|
||||
ax[:annotate]("",
|
||||
ax."annotate"("",
|
||||
xytext = (0.001xyprev[1] + 0.999xy[1], 0.001xyprev[2] + 0.999xy[2]),
|
||||
xy = xy,
|
||||
arrowprops = arrowprops,
|
||||
@@ -514,7 +519,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
for i=1:length(y)
|
||||
extrakw[:c] = _cycle(markercolor, i)
|
||||
|
||||
push!(handle, ax[:scatter](_cycle(x,i), _cycle(y,i);
|
||||
push!(handle, ax."scatter"(_cycle(x,i), _cycle(y,i);
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = py_marker(_cycle(shapes,i)),
|
||||
@@ -524,10 +529,72 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
extrakw...
|
||||
))
|
||||
end
|
||||
push!(handles, handle)
|
||||
elseif isa(series[:markershape], AbstractVector{Symbol})
|
||||
handle = []
|
||||
x,y = xyargs
|
||||
shapes = series[:markershape]
|
||||
|
||||
prev_marker = py_marker(_cycle(shapes,1))
|
||||
|
||||
cur_x_list = []
|
||||
cur_y_list = []
|
||||
|
||||
cur_color_list = []
|
||||
cur_scale_list = []
|
||||
|
||||
delete!(extrakw, :c)
|
||||
|
||||
for i=1:length(y)
|
||||
cur_marker = py_marker(_cycle(shapes,i))
|
||||
|
||||
if ( cur_marker == prev_marker )
|
||||
push!(cur_x_list, _cycle(x,i))
|
||||
push!(cur_y_list, _cycle(y,i))
|
||||
|
||||
push!(cur_color_list, _cycle(markercolor, i))
|
||||
push!(cur_scale_list, py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2))
|
||||
|
||||
continue
|
||||
end
|
||||
|
||||
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = prev_marker,
|
||||
s = cur_scale_list,
|
||||
edgecolors = py_markerstrokecolor(series),
|
||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
||||
facecolors = cur_color_list,
|
||||
extrakw...
|
||||
))
|
||||
|
||||
cur_x_list = [_cycle(x,i)]
|
||||
cur_y_list = [_cycle(y,i)]
|
||||
|
||||
cur_color_list = [_cycle(markercolor, i)]
|
||||
cur_scale_list = [py_thickness_scale(plt, _cycle(series[:markersize],i) .^ 2)]
|
||||
|
||||
prev_marker = cur_marker
|
||||
end
|
||||
|
||||
if !isempty(cur_color_list)
|
||||
push!(handle, ax."scatter"(cur_x_list, cur_y_list;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = prev_marker,
|
||||
s = cur_scale_list,
|
||||
edgecolors = py_markerstrokecolor(series),
|
||||
linewidths = py_thickness_scale(plt, series[:markerstrokewidth]),
|
||||
facecolors = cur_color_list,
|
||||
extrakw...
|
||||
))
|
||||
end
|
||||
|
||||
push!(handles, handle)
|
||||
else
|
||||
# do a normal scatter plot
|
||||
handle = ax[:scatter](xyargs...;
|
||||
handle = ax."scatter"(xyargs...;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
marker = py_marker(series[:markershape]),
|
||||
@@ -541,7 +608,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
if st == :hexbin
|
||||
handle = ax[:hexbin](x, y;
|
||||
handle = ax."hexbin"(x, y;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
gridsize = series[:bins],
|
||||
@@ -573,7 +640,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
# contour lines
|
||||
handle = ax[:contour](x, y, z, levelargs...;
|
||||
handle = ax."contour"(x, y, z, levelargs...;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
linewidths = py_thickness_scale(plt, series[:linewidth]),
|
||||
@@ -581,13 +648,13 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
extrakw...
|
||||
)
|
||||
if series[:contour_labels] == true
|
||||
PyPlot.clabel(handle, handle[:levels])
|
||||
PyPlot."clabel"(handle, handle.levels)
|
||||
end
|
||||
push!(handles, handle)
|
||||
|
||||
# contour fills
|
||||
if series[:fillrange] != nothing
|
||||
handle = ax[:contourf](x, y, z, levelargs...;
|
||||
handle = ax."contourf"(x, y, z, levelargs...;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex] + 0.5,
|
||||
extrakw...
|
||||
@@ -613,7 +680,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
extrakw[:cmap] = py_fillcolormap(series)
|
||||
end
|
||||
end
|
||||
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
|
||||
handle = getproperty(ax, st == :surface ? :plot_surface : :plot_wireframe)(x, y, z;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
rstride = series[:stride][1],
|
||||
@@ -628,7 +695,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
if series[:contours]
|
||||
for (zdir,mat) in (("x",x), ("y",y), ("z",z))
|
||||
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat)
|
||||
handle = ax[:contourf](x, y, z, levelargs...;
|
||||
handle = ax."contourf"(x, y, z, levelargs...;
|
||||
zdir = zdir,
|
||||
cmap = py_fillcolormap(series),
|
||||
offset = (zdir == "y" ? ignorenan_maximum : ignorenan_minimum)(mat) # where to draw the contour plane
|
||||
@@ -640,7 +707,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
|
||||
elseif typeof(z) <: AbstractVector
|
||||
# tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots)
|
||||
handle = ax[:plot_trisurf](x, y, z;
|
||||
handle = ax."plot_trisurf"(x, y, z;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
cmap = py_fillcolormap(series),
|
||||
@@ -665,9 +732,9 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
else
|
||||
z # hopefully it's in a data format that will "just work" with imshow
|
||||
end
|
||||
handle = ax[:imshow](z;
|
||||
handle = ax."imshow"(z;
|
||||
zorder = series[:series_plotindex],
|
||||
cmap = py_colormap([:black, :white]),
|
||||
cmap = py_colormap(cgrad([:black, :white])),
|
||||
vmin = 0.0,
|
||||
vmax = 1.0,
|
||||
extent = (xmin, xmax, ymax, ymin)
|
||||
@@ -675,7 +742,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
push!(handles, handle)
|
||||
|
||||
# expand extrema... handle is AxesImage object
|
||||
xmin, xmax, ymax, ymin = handle[:get_extent]()
|
||||
xmin, xmax, ymax, ymin = handle."get_extent"()
|
||||
expand_extrema!(sp, xmin, xmax, ymin, ymax)
|
||||
# sp[:yaxis].series[:flip] = true
|
||||
end
|
||||
@@ -690,7 +757,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
discrete_colorbar_values = dvals
|
||||
end
|
||||
|
||||
handle = ax[:pcolormesh](x, y, py_mask_nans(z);
|
||||
handle = ax."pcolormesh"(x, y, py_mask_nans(z);
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
cmap = py_fillcolormap(series),
|
||||
@@ -705,8 +772,8 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
handle = []
|
||||
for (i, rng) in enumerate(iter_segments(series))
|
||||
if length(rng) > 1
|
||||
path = pypath["Path"](hcat(x[rng], y[rng]))
|
||||
patches = pypatches["PathPatch"](
|
||||
path = pypath."Path"(hcat(x[rng], y[rng]))
|
||||
patches = pypatches."PathPatch"(
|
||||
path;
|
||||
label = series[:label],
|
||||
zorder = series[:series_plotindex],
|
||||
@@ -716,14 +783,14 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
linestyle = py_linestyle(st, get_linestyle(series, i)),
|
||||
fill = true
|
||||
)
|
||||
push!(handle, ax[:add_patch](patches))
|
||||
push!(handle, ax."add_patch"(patches))
|
||||
end
|
||||
end
|
||||
push!(handles, handle)
|
||||
end
|
||||
|
||||
if st == :pie
|
||||
handle = ax[:pie](y;
|
||||
handle = ax."pie"(y;
|
||||
# colors = # a vector of colors?
|
||||
labels = pie_labels(sp, series)
|
||||
)[1]
|
||||
@@ -758,7 +825,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
dim1, _cycle(fillrange[1], rng), _cycle(fillrange[2], rng)
|
||||
end
|
||||
|
||||
handle = ax[f](args..., trues(n), false, py_fillstepstyle(st);
|
||||
handle = getproperty(ax, f)(args..., trues(n), false, py_fillstepstyle(st);
|
||||
zorder = series[:series_plotindex],
|
||||
facecolor = py_color(get_fillcolor(series, clims, i), get_fillalpha(series, i)),
|
||||
linewidths = 0
|
||||
@@ -779,27 +846,27 @@ end
|
||||
function py_set_lims(ax, axis::Axis)
|
||||
letter = axis[:letter]
|
||||
lfrom, lto = axis_limits(axis)
|
||||
ax[Symbol("set_", letter, "lim")](lfrom, lto)
|
||||
getproperty(ax, Symbol("set_", letter, "lim"))(lfrom, lto)
|
||||
end
|
||||
|
||||
function py_set_ticks(ax, ticks, letter)
|
||||
ticks == :auto && return
|
||||
axis = ax[Symbol(letter,"axis")]
|
||||
axis = getproperty(ax, Symbol(letter,"axis"))
|
||||
if ticks == :none || ticks == nothing || ticks == false
|
||||
kw = KW()
|
||||
for dir in (:top,:bottom,:left,:right)
|
||||
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||
end
|
||||
axis[:set_tick_params](;which="both", kw...)
|
||||
axis."set_tick_params"(;which="both", kw...)
|
||||
return
|
||||
end
|
||||
|
||||
ttype = ticksType(ticks)
|
||||
if ttype == :ticks
|
||||
axis[:set_ticks](ticks)
|
||||
axis."set_ticks"(ticks)
|
||||
elseif ttype == :ticks_and_labels
|
||||
axis[:set_ticks](ticks[1])
|
||||
axis[:set_ticklabels](ticks[2])
|
||||
axis."set_ticks"(ticks[1])
|
||||
axis."set_ticklabels"(ticks[2])
|
||||
else
|
||||
error("Invalid input for $(letter)ticks: $ticks")
|
||||
end
|
||||
@@ -829,7 +896,7 @@ function py_set_scale(ax, axis::Axis)
|
||||
scale = axis[:scale]
|
||||
letter = axis[:letter]
|
||||
scale in supported_scales() || return @warn("Unhandled scale value in pyplot: $scale")
|
||||
func = ax[Symbol("set_", letter, "scale")]
|
||||
func = getproperty(ax, Symbol("set_", letter, "scale"))
|
||||
kw = KW()
|
||||
arg = if scale == :identity
|
||||
"linear"
|
||||
@@ -849,16 +916,16 @@ end
|
||||
|
||||
|
||||
function py_set_axis_colors(sp, ax, a::Axis)
|
||||
for (loc, spine) in ax[:spines]
|
||||
spine[:set_color](py_color(a[:foreground_color_border]))
|
||||
for (loc, spine) in ax.spines
|
||||
spine."set_color"(py_color(a[:foreground_color_border]))
|
||||
end
|
||||
axissym = Symbol(a[:letter], :axis)
|
||||
if haskey(ax, axissym)
|
||||
if PyCall.hasproperty(ax, axissym)
|
||||
tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis])
|
||||
ax[:tick_params](axis=string(a[:letter]), which="both",
|
||||
ax."tick_params"(axis=string(a[:letter]), which="both",
|
||||
colors=tickcolor,
|
||||
labelcolor=py_color(a[:tickfontcolor]))
|
||||
ax[axissym][:label][:set_color](py_color(a[:guidefontcolor]))
|
||||
getproperty(ax, axissym).label.set_color(py_color(a[:guidefontcolor]))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -870,14 +937,14 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
# update the fig
|
||||
w, h = plt[:size]
|
||||
fig = plt.o
|
||||
fig[:clear]()
|
||||
fig."clear"()
|
||||
dpi = plt[:dpi]
|
||||
fig[:set_size_inches](w/DPI, h/DPI, forward = true)
|
||||
fig[set_facecolor_sym](py_color(plt[:background_color_outside]))
|
||||
fig[:set_dpi](plt[:dpi])
|
||||
fig."set_size_inches"(w/DPI, h/DPI, forward = true)
|
||||
getproperty(fig, set_facecolor_sym)(py_color(plt[:background_color_outside]))
|
||||
fig."set_dpi"(plt[:dpi])
|
||||
|
||||
# resize the window
|
||||
PyPlot.plt[:get_current_fig_manager]()[:resize](w, h)
|
||||
PyPlot.plt."get_current_fig_manager"().resize(w, h)
|
||||
|
||||
# initialize subplots
|
||||
for sp in plt.subplots
|
||||
@@ -911,10 +978,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
else
|
||||
:title
|
||||
end
|
||||
ax[func][:set_text](sp[:title])
|
||||
ax[func][:set_fontsize](py_thickness_scale(plt, sp[:titlefontsize]))
|
||||
ax[func][:set_family](sp[:titlefontfamily])
|
||||
ax[func][:set_color](py_color(sp[:titlefontcolor]))
|
||||
getproperty(ax, func)."set_text"(sp[:title])
|
||||
getproperty(ax, func)."set_fontsize"(py_thickness_scale(plt, sp[:titlefontsize]))
|
||||
getproperty(ax, func)."set_family"(sp[:titlefontfamily])
|
||||
getproperty(ax, func)."set_color"(py_color(sp[:titlefontcolor]))
|
||||
# ax[:set_title](sp[:title], loc = loc)
|
||||
end
|
||||
|
||||
@@ -934,7 +1001,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
kw[:boundaries] = vcat(0, kw[:values] + 0.5)
|
||||
elseif any(colorbar_series[attr] != nothing for attr in (:line_z, :fill_z, :marker_z))
|
||||
cmin, cmax = get_clims(sp)
|
||||
norm = pycolors[:Normalize](vmin = cmin, vmax = cmax)
|
||||
norm = pycolors."Normalize"(vmin = cmin, vmax = cmax)
|
||||
f = if colorbar_series[:line_z] != nothing
|
||||
py_linecolormap
|
||||
elseif colorbar_series[:fill_z] != nothing
|
||||
@@ -942,21 +1009,21 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
else
|
||||
py_markercolormap
|
||||
end
|
||||
cmap = pycmap[:ScalarMappable](norm = norm, cmap = f(colorbar_series))
|
||||
cmap[:set_array]([])
|
||||
cmap = pycmap."ScalarMappable"(norm = norm, cmap = f(colorbar_series))
|
||||
cmap."set_array"([])
|
||||
handle = cmap
|
||||
end
|
||||
|
||||
# create and store the colorbar object (handle) and the axis that it is drawn on.
|
||||
# note: the colorbar axis is positioned independently from the subplot axis
|
||||
fig = plt.o
|
||||
cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym()))
|
||||
cb = fig[:colorbar](handle; cax = cbax, kw...)
|
||||
cb[:set_label](sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
|
||||
for lab in cb[:ax][:yaxis][:get_ticklabels]()
|
||||
lab[:set_fontsize](py_thickness_scale(plt, sp[:yaxis][:tickfontsize]))
|
||||
lab[:set_family](sp[:yaxis][:tickfontfamily])
|
||||
lab[:set_color](py_color(sp[:yaxis][:tickfontcolor]))
|
||||
cbax = fig."add_axes"([0.8,0.1,0.03,0.8], label = string(gensym()))
|
||||
cb = fig."colorbar"(handle; cax = cbax, kw...)
|
||||
cb."set_label"(sp[:colorbar_title],size=py_thickness_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
|
||||
for lab in cb."ax"."yaxis"."get_ticklabels"()
|
||||
lab."set_fontsize"(py_thickness_scale(plt, sp[:yaxis][:tickfontsize]))
|
||||
lab."set_family"(sp[:yaxis][:tickfontfamily])
|
||||
lab."set_color"(py_color(sp[:yaxis][:tickfontcolor]))
|
||||
end
|
||||
sp.attr[:cbar_handle] = cb
|
||||
sp.attr[:cbar_ax] = cbax
|
||||
@@ -964,28 +1031,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
|
||||
# framestyle
|
||||
if !ispolar(sp) && !is3d(sp)
|
||||
ax[:spines]["left"][:set_linewidth](py_thickness_scale(plt, 1))
|
||||
ax[:spines]["bottom"][:set_linewidth](py_thickness_scale(plt, 1))
|
||||
ax.spines["left"]."set_linewidth"(py_thickness_scale(plt, 1))
|
||||
ax.spines["bottom"]."set_linewidth"(py_thickness_scale(plt, 1))
|
||||
if sp[:framestyle] == :semi
|
||||
intensity = 0.5
|
||||
ax[:spines]["right"][:set_alpha](intensity)
|
||||
ax[:spines]["top"][:set_alpha](intensity)
|
||||
ax[:spines]["right"][:set_linewidth](py_thickness_scale(plt, intensity))
|
||||
ax[:spines]["top"][:set_linewidth](py_thickness_scale(plt, intensity))
|
||||
ax.spines["right"]."set_alpha"(intensity)
|
||||
ax.spines["top"]."set_alpha"(intensity)
|
||||
ax.spines["right"]."set_linewidth"(py_thickness_scale(plt, intensity))
|
||||
ax.spines["top"]."set_linewidth"(py_thickness_scale(plt, intensity))
|
||||
elseif sp[:framestyle] in (:axes, :origin)
|
||||
ax[:spines]["right"][:set_visible](false)
|
||||
ax[:spines]["top"][:set_visible](false)
|
||||
ax.spines["right"]."set_visible"(false)
|
||||
ax.spines["top"]."set_visible"(false)
|
||||
if sp[:framestyle] == :origin
|
||||
ax[:spines]["bottom"][:set_position]("zero")
|
||||
ax[:spines]["left"][:set_position]("zero")
|
||||
ax.spines["bottom"]."set_position"("zero")
|
||||
ax.spines["left"]."set_position"("zero")
|
||||
end
|
||||
elseif sp[:framestyle] in (:grid, :none, :zerolines)
|
||||
for (loc, spine) in ax[:spines]
|
||||
spine[:set_visible](false)
|
||||
for (loc, spine) in ax.spines
|
||||
spine."set_visible"(false)
|
||||
end
|
||||
if sp[:framestyle] == :zerolines
|
||||
ax[:axhline](y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
|
||||
ax[:axvline](x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
|
||||
ax."axhline"(y = 0, color = py_color(sp[:xaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
|
||||
ax."axvline"(x = 0, color = py_color(sp[:yaxis][:foreground_color_axis]), lw = py_thickness_scale(plt, 0.75))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -993,22 +1060,22 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
# axis attributes
|
||||
for letter in (:x, :y, :z)
|
||||
axissym = Symbol(letter, :axis)
|
||||
haskey(ax, axissym) || continue
|
||||
PyCall.hasproperty(ax, axissym) || continue
|
||||
axis = sp[axissym]
|
||||
pyaxis = ax[axissym]
|
||||
pyaxis = getproperty(ax, axissym)
|
||||
if axis[:mirror] && letter != :z
|
||||
pos = letter == :x ? "top" : "right"
|
||||
pyaxis[:set_label_position](pos) # the guides
|
||||
pyaxis[:set_ticks_position]("both") # the hash marks
|
||||
pyaxis[Symbol(:tick_, pos)]() # the tick labels
|
||||
pyaxis."set_label_position"(pos) # the guides
|
||||
pyaxis."set_ticks_position"("both") # the hash marks
|
||||
getproperty(pyaxis, Symbol(:tick_, pos))() # the tick labels
|
||||
end
|
||||
if axis[:guide_position] != :auto && letter != :z
|
||||
pyaxis[:set_label_position](axis[:guide_position])
|
||||
pyaxis."set_label_position"(axis[:guide_position])
|
||||
end
|
||||
py_set_scale(ax, axis)
|
||||
axis[:ticks] != :native ? py_set_lims(ax, axis) : nothing
|
||||
if ispolar(sp) && letter == :y
|
||||
ax[:set_rlabel_position](90)
|
||||
ax."set_rlabel_position"(90)
|
||||
end
|
||||
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
|
||||
# don't show the 0 tick label for the origin framestyle
|
||||
@@ -1016,28 +1083,28 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
ticks[2][ticks[1] .== 0] .= ""
|
||||
end
|
||||
axis[:ticks] != :native ? py_set_ticks(ax, ticks, letter) : nothing
|
||||
pyaxis[:set_tick_params](direction = axis[:tick_direction] == :out ? "out" : "in")
|
||||
ax[Symbol("set_", letter, "label")](axis[:guide])
|
||||
pyaxis."set_tick_params"(direction = axis[:tick_direction] == :out ? "out" : "in")
|
||||
getproperty(ax, Symbol("set_", letter, "label"))(axis[:guide])
|
||||
if get(axis.plotattributes, :flip, false)
|
||||
ax[Symbol("invert_", letter, "axis")]()
|
||||
getproperty(ax, Symbol("invert_", letter, "axis"))()
|
||||
end
|
||||
pyaxis[:label][:set_fontsize](py_thickness_scale(plt, axis[:guidefontsize]))
|
||||
pyaxis[:label][:set_family](axis[:guidefontfamily])
|
||||
for lab in ax[Symbol("get_", letter, "ticklabels")]()
|
||||
lab[:set_fontsize](py_thickness_scale(plt, axis[:tickfontsize]))
|
||||
lab[:set_family](axis[:tickfontfamily])
|
||||
lab[:set_rotation](axis[:rotation])
|
||||
pyaxis."label"."set_fontsize"(py_thickness_scale(plt, axis[:guidefontsize]))
|
||||
pyaxis."label"."set_family"(axis[:guidefontfamily])
|
||||
for lab in getproperty(ax, Symbol("get_", letter, "ticklabels"))()
|
||||
lab."set_fontsize"(py_thickness_scale(plt, axis[:tickfontsize]))
|
||||
lab."set_family"(axis[:tickfontfamily])
|
||||
lab."set_rotation"(axis[:rotation])
|
||||
end
|
||||
if axis[:grid] && !(ticks in (:none, nothing, false))
|
||||
fgcolor = py_color(axis[:foreground_color_grid])
|
||||
pyaxis[:grid](true,
|
||||
pyaxis."grid"(true,
|
||||
color = fgcolor,
|
||||
linestyle = py_linestyle(:line, axis[:gridstyle]),
|
||||
linewidth = py_thickness_scale(plt, axis[:gridlinewidth]),
|
||||
alpha = axis[:gridalpha])
|
||||
ax[:set_axisbelow](true)
|
||||
ax."set_axisbelow"(true)
|
||||
else
|
||||
pyaxis[:grid](false)
|
||||
pyaxis."grid"(false)
|
||||
end
|
||||
py_set_axis_colors(sp, ax, axis)
|
||||
end
|
||||
@@ -1047,48 +1114,48 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
kw = KW()
|
||||
for dir in (:top, :bottom)
|
||||
if ispolar(sp)
|
||||
ax[:spines]["polar"][:set_visible](false)
|
||||
ax."spines"."polar"."set_visible"(false)
|
||||
else
|
||||
ax[:spines][string(dir)][:set_visible](false)
|
||||
getproperty(ax.spines, dir).set_visible(false)
|
||||
end
|
||||
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||
end
|
||||
ax[:xaxis][:set_tick_params](; which="both", kw...)
|
||||
ax."xaxis"."set_tick_params"(; which="both", kw...)
|
||||
end
|
||||
if !sp[:yaxis][:showaxis]
|
||||
kw = KW()
|
||||
for dir in (:left, :right)
|
||||
if !ispolar(sp)
|
||||
ax[:spines][string(dir)][:set_visible](false)
|
||||
getproperty(ax.spines, dir).set_visible(false)
|
||||
end
|
||||
kw[dir] = kw[Symbol(:label,dir)] = false
|
||||
end
|
||||
ax[:yaxis][:set_tick_params](; which="both", kw...)
|
||||
ax."yaxis"."set_tick_params"(; which="both", kw...)
|
||||
end
|
||||
|
||||
# aspect ratio
|
||||
aratio = sp[:aspect_ratio]
|
||||
if aratio != :none
|
||||
ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
|
||||
ax."set_aspect"(isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
|
||||
end
|
||||
|
||||
#camera/view angle
|
||||
if is3d(sp)
|
||||
#convert azimuthal to match GR behaviour
|
||||
#view_init(elevation, azimuthal) so reverse :camera args
|
||||
ax[:view_init]((sp[:camera].-(90,0))[end:-1:1]...)
|
||||
ax."view_init"((sp[:camera].-(90,0))[end:-1:1]...)
|
||||
end
|
||||
|
||||
# legend
|
||||
py_add_legend(plt, sp, ax)
|
||||
|
||||
# this sets the bg color inside the grid
|
||||
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
|
||||
getproperty(ax, set_facecolor_sym)(py_color(sp[:background_color_inside]))
|
||||
|
||||
# link axes
|
||||
x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o
|
||||
ax != x_ax_link && ax[:get_shared_x_axes]()[:join](ax, sp[:xaxis].sps[1].o)
|
||||
ax != y_ax_link && ax[:get_shared_y_axes]()[:join](ax, sp[:yaxis].sps[1].o)
|
||||
ax != x_ax_link && ax."get_shared_x_axes"()."join"(ax, sp[:xaxis].sps[1].o)
|
||||
ax != y_ax_link && ax."get_shared_y_axes"()."join"(ax, sp[:yaxis].sps[1].o)
|
||||
end
|
||||
py_drawfig(fig)
|
||||
end
|
||||
@@ -1119,7 +1186,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend})
|
||||
|
||||
# optionally add the width of colorbar labels and colorbar to rightpad
|
||||
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) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||
rightpad = rightpad + sp.attr[:cbar_width]
|
||||
end
|
||||
@@ -1140,19 +1207,19 @@ end
|
||||
|
||||
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val)
|
||||
ax = sp.o
|
||||
ax[:annotate](val, xy = (x,y), zorder = 999)
|
||||
ax."annotate"(val, xy = (x,y), zorder = 999)
|
||||
end
|
||||
|
||||
|
||||
function py_add_annotations(sp::Subplot{PyPlotBackend}, x, y, val::PlotText)
|
||||
ax = sp.o
|
||||
ax[:annotate](val.str,
|
||||
ax."annotate"(val.str,
|
||||
xy = (x,y),
|
||||
family = val.font.family,
|
||||
color = py_color(val.font.color),
|
||||
horizontalalignment = val.font.halign == :hcenter ? "center" : string(val.font.halign),
|
||||
verticalalignment = val.font.valign == :vcenter ? "center" : string(val.font.valign),
|
||||
rotation = val.font.rotation * 180 / π,
|
||||
rotation = val.font.rotation,
|
||||
size = py_thickness_scale(sp.plt, val.font.pointsize),
|
||||
zorder = 999
|
||||
)
|
||||
@@ -1182,18 +1249,18 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
||||
if should_add_to_legend(series)
|
||||
# add a line/marker and a label
|
||||
push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
|
||||
pypatches[:Patch](
|
||||
pypatches."Patch"(
|
||||
edgecolor = py_color(get_linecolor(series, clims), get_linealpha(series)),
|
||||
facecolor = py_color(get_fillcolor(series, clims), get_fillalpha(series)),
|
||||
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
|
||||
linestyle = py_linestyle(series[:seriestype], get_linestyle(series))
|
||||
)
|
||||
elseif series[:seriestype] in (:path, :straightline)
|
||||
PyPlot.plt[:Line2D]((0,1),(0,0),
|
||||
elseif series[:seriestype] in (:path, :straightline, :scatter)
|
||||
PyPlot.plt."Line2D"((0,1),(0,0),
|
||||
color = py_color(get_linecolor(series, clims), get_linealpha(series)),
|
||||
linewidth = py_thickness_scale(plt, clamp(get_linewidth(series), 0, 5)),
|
||||
linestyle = py_linestyle(:path, get_linestyle(series)),
|
||||
marker = py_marker(series[:markershape]),
|
||||
marker = py_marker(first(series[:markershape])),
|
||||
markeredgecolor = py_color(get_markerstrokecolor(series), get_markerstrokealpha(series)),
|
||||
markerfacecolor = series[:marker_z] == nothing ? py_color(get_markercolor(series, clims), get_markeralpha(series)) : py_color(series[:markercolor][0.5])
|
||||
)
|
||||
@@ -1206,7 +1273,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
||||
|
||||
# if anything was added, call ax.legend and set the colors
|
||||
if !isempty(handles)
|
||||
leg = ax[:legend](handles,
|
||||
leg = ax."legend"(handles,
|
||||
labels,
|
||||
loc = get(_pyplot_legend_pos, leg, "best"),
|
||||
scatterpoints = 1,
|
||||
@@ -1215,13 +1282,13 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
||||
edgecolor = py_color(sp[:foreground_color_legend]),
|
||||
framealpha = alpha(plot_color(sp[:background_color_legend])),
|
||||
)
|
||||
frame = leg[:get_frame]()
|
||||
frame[:set_linewidth](py_thickness_scale(plt, 1))
|
||||
leg[:set_zorder](1000)
|
||||
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
|
||||
frame = leg."get_frame"()
|
||||
frame."set_linewidth"(py_thickness_scale(plt, 1))
|
||||
leg."set_zorder"(1000)
|
||||
sp[:legendtitle] != nothing && leg."set_title"(sp[:legendtitle])
|
||||
|
||||
for txt in leg[:get_texts]()
|
||||
PyPlot.plt[:setp](txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
|
||||
for txt in leg."get_texts"()
|
||||
PyPlot.plt."setp"(txt, color = py_color(sp[:legendfontcolor]), family = sp[:legendfontfamily])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1239,7 +1306,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
|
||||
figw, figh = sp.plt[:size]
|
||||
figw, figh = figw*px, figh*px
|
||||
pcts = bbox_to_pcts(sp.plotarea, figw, figh)
|
||||
ax[:set_position](pcts)
|
||||
ax."set_position"(pcts)
|
||||
|
||||
# set the cbar position if there is one
|
||||
if haskey(sp.attr, :cbar_ax)
|
||||
@@ -1249,7 +1316,7 @@ function _update_plot_object(plt::Plot{PyPlotBackend})
|
||||
has_toplabel = !(1e-7 < max(abs(ex.emax), abs(ex.emin)) < 1e7)
|
||||
cb_bbox = BoundingBox(right(sp.bbox)-cbw+1mm, top(sp.bbox) + (has_toplabel ? 4mm : 2mm), _cbar_width-1mm, height(sp.bbox) - (has_toplabel ? 6mm : 4mm))
|
||||
pcts = bbox_to_pcts(cb_bbox, figw, figh)
|
||||
sp.attr[:cbar_ax][:set_position](pcts)
|
||||
sp.attr[:cbar_ax]."set_position"(pcts)
|
||||
end
|
||||
end
|
||||
PyPlot.draw()
|
||||
@@ -1258,9 +1325,7 @@ end
|
||||
# -----------------------------------------------------------------
|
||||
# display/output
|
||||
|
||||
function _display(plt::Plot{PyPlotBackend})
|
||||
plt.o[:show]()
|
||||
end
|
||||
_display(plt::Plot{PyPlotBackend}) = plt.o."show"()
|
||||
|
||||
|
||||
|
||||
@@ -1270,23 +1335,24 @@ const _pyplot_mimeformats = Dict(
|
||||
"application/pdf" => "pdf",
|
||||
"image/png" => "png",
|
||||
"application/postscript" => "ps",
|
||||
"image/svg+xml" => "svg"
|
||||
"image/svg+xml" => "svg",
|
||||
"application/x-tex" => "pgf"
|
||||
)
|
||||
|
||||
|
||||
for (mime, fmt) in _pyplot_mimeformats
|
||||
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend})
|
||||
fig = plt.o
|
||||
fig[:canvas][:print_figure](
|
||||
fig."canvas"."print_figure"(
|
||||
io,
|
||||
format=$fmt,
|
||||
# bbox_inches = "tight",
|
||||
# figsize = map(px2inch, plt[:size]),
|
||||
facecolor = fig[:get_facecolor](),
|
||||
facecolor = fig."get_facecolor"(),
|
||||
edgecolor = "none",
|
||||
dpi = plt[:dpi]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
closeall(::PyPlotBackend) = PyPlot.plt[:close]("all")
|
||||
closeall(::PyPlotBackend) = PyPlot.plt."close"("all")
|
||||
|
||||
@@ -116,7 +116,7 @@ function addUnicodeSeries!(o, plotattributes::KW, addlegend::Bool, xlim, ylim)
|
||||
x, y = if st == :straightline
|
||||
straightline_data(plotattributes)
|
||||
elseif st == :shape
|
||||
shape_data(series)
|
||||
shape_data(plotattributes)
|
||||
else
|
||||
[collect(float(plotattributes[s])) for s in (:x, :y)]
|
||||
end
|
||||
|
||||
+49
-6
@@ -256,8 +256,24 @@ mutable struct Font
|
||||
color::Colorant
|
||||
end
|
||||
|
||||
"Create a Font from a list of unordered features"
|
||||
function font(args...)
|
||||
"""
|
||||
font(args...)
|
||||
Create a Font from a list of features. Values may be specified either as
|
||||
arguments (which are distinguished by type/value) or as keyword arguments.
|
||||
# Arguments
|
||||
- `family`: AbstractString. "serif" or "sans-serif" or "monospace"
|
||||
- `pointsize`: Integer. Size of font in points
|
||||
- `halign`: Symbol. Horizontal alignment (:hcenter, :left, or :right)
|
||||
- `valign`: Symbol. Vertical aligment (:vcenter, :top, or :bottom)
|
||||
- `rotation`: Real. Angle of rotation for text in degrees (use a non-integer type)
|
||||
- `color`: Colorant or Symbol
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> font(8)
|
||||
julia> font(family="serif",halign=:center,rotation=45.0)
|
||||
```
|
||||
"""
|
||||
function font(args...;kw...)
|
||||
|
||||
# defaults
|
||||
family = "sans-serif"
|
||||
@@ -301,6 +317,32 @@ function font(args...)
|
||||
end
|
||||
end
|
||||
|
||||
for symbol in keys(kw)
|
||||
if symbol == :family
|
||||
family = kw[:family]
|
||||
elseif symbol == :pointsize
|
||||
pointsize = kw[:pointsize]
|
||||
elseif symbol == :halign
|
||||
halign = kw[:halign]
|
||||
if halign == :center
|
||||
halign = :hcenter
|
||||
end
|
||||
@assert halign in (:hcenter, :left, :right)
|
||||
elseif symbol == :valign
|
||||
valign = kw[:valign]
|
||||
if valign == :center
|
||||
valign = :vcenter
|
||||
end
|
||||
@assert valign in (:vcenter, :top, :bottom)
|
||||
elseif symbol == :rotation
|
||||
rotation = kw[:rotation]
|
||||
elseif symbol == :color
|
||||
color = parse(Colorant, kw[:color])
|
||||
else
|
||||
@warn("Unused font kwarg: $symbol")
|
||||
end
|
||||
end
|
||||
|
||||
Font(family, pointsize, halign, valign, rotation, color)
|
||||
end
|
||||
|
||||
@@ -344,15 +386,16 @@ end
|
||||
PlotText(str) = PlotText(string(str), font())
|
||||
|
||||
"""
|
||||
text(string, args...)
|
||||
text(string, args...; kw...)
|
||||
|
||||
Create a PlotText object wrapping a string with font info, for plot annotations
|
||||
Create a PlotText object wrapping a string with font info, for plot annotations.
|
||||
`args` and `kw` are passed to `font`.
|
||||
"""
|
||||
text(t::PlotText) = t
|
||||
text(t::PlotText, font::Font) = PlotText(t.str, font)
|
||||
text(str::AbstractString, f::Font) = PlotText(str, f)
|
||||
function text(str, args...)
|
||||
PlotText(string(str), font(args...))
|
||||
function text(str, args...;kw...)
|
||||
PlotText(string(str), font(args...;kw...))
|
||||
end
|
||||
|
||||
Base.length(t::PlotText) = length(t.str)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# ---------------------------------------------------------
|
||||
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
|
||||
|
||||
_fileio_load(@nospecialize(filename::AbstractString)) = FileIO.load(filename::AbstractString)
|
||||
_fileio_save(@nospecialize(filename::AbstractString), @nospecialize(x)) = FileIO.save(filename::AbstractString, x)
|
||||
|
||||
function _show_pdfbackends(io::IO, ::MIME"image/png", plt::Plot)
|
||||
fn = tempname()
|
||||
|
||||
# first save a pdf file
|
||||
pdf(plt, fn)
|
||||
|
||||
# load that pdf into a FileIO Stream
|
||||
s = _fileio_load(fn * ".pdf")
|
||||
|
||||
# save a png
|
||||
pngfn = fn * ".png"
|
||||
_fileio_save(pngfn, s)
|
||||
|
||||
# now write from the file
|
||||
write(io, read(open(pngfn), String))
|
||||
end
|
||||
|
||||
const PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
|
||||
@@ -0,0 +1,59 @@
|
||||
const use_local_dependencies = Ref(false)
|
||||
const use_local_plotlyjs = Ref(false)
|
||||
|
||||
|
||||
function _init_ijulia_plotting()
|
||||
# IJulia is more stable with local file
|
||||
use_local_plotlyjs[] = isfile(plotly_local_file_path)
|
||||
|
||||
ENV["MPLBACKEND"] = "Agg"
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
Add extra jupyter mimetypes to display_dict based on the plot backed.
|
||||
|
||||
The default is nothing, except for plotly based backends, where it
|
||||
adds data for `application/vnd.plotly.v1+json` that is used in
|
||||
frontends like jupyterlab and nteract.
|
||||
"""
|
||||
_ijulia__extra_mime_info!(plt::Plot, out::Dict) = out
|
||||
|
||||
function _ijulia__extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
|
||||
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
|
||||
out
|
||||
end
|
||||
|
||||
function _ijulia__extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
|
||||
out["application/vnd.plotly.v1+json"] = Dict(
|
||||
:data => plotly_series(plt),
|
||||
:layout => plotly_layout(plt)
|
||||
)
|
||||
out
|
||||
end
|
||||
|
||||
|
||||
function _ijulia_display_dict(plt::Plot)
|
||||
output_type = Symbol(plt.attr[:html_output_format])
|
||||
if output_type == :auto
|
||||
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
|
||||
end
|
||||
out = Dict()
|
||||
if output_type == :txt
|
||||
mime = "text/plain"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
elseif output_type == :png
|
||||
mime = "image/png"
|
||||
out[mime] = base64encode(show, MIME(mime), plt)
|
||||
elseif output_type == :svg
|
||||
mime = "image/svg+xml"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
elseif output_type == :html
|
||||
mime = "text/html"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
else
|
||||
error("Unsupported output type $output_type")
|
||||
end
|
||||
_ijulia__extra_mime_info!(plt, out)
|
||||
out
|
||||
end
|
||||
+22
-85
@@ -1,16 +1,22 @@
|
||||
using REPL
|
||||
|
||||
const use_local_dependencies = Ref(false)
|
||||
|
||||
function _plots_defaults()
|
||||
if isdefined(Main, :PLOTS_DEFAULTS)
|
||||
Dict{Symbol,Any}(Main.PLOTS_DEFAULTS)
|
||||
else
|
||||
Dict{Symbol,Any}()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function __init__()
|
||||
|
||||
if isdefined(Main, :PLOTS_DEFAULTS)
|
||||
if haskey(Main.PLOTS_DEFAULTS, :theme)
|
||||
theme(Main.PLOTS_DEFAULTS[:theme])
|
||||
end
|
||||
for (k,v) in Main.PLOTS_DEFAULTS
|
||||
k == :theme || default(k, v)
|
||||
end
|
||||
user_defaults = _plots_defaults()
|
||||
if haskey(user_defaults, :theme)
|
||||
theme(user_defaults[:theme])
|
||||
end
|
||||
for (k,v) in user_defaults
|
||||
k == :theme || default(k, v)
|
||||
end
|
||||
|
||||
insert!(Base.Multimedia.displays, findlast(x -> x isa Base.TextDisplay || x isa REPL.REPLDisplay, Base.Multimedia.displays) + 1, PlotsDisplay())
|
||||
@@ -29,95 +35,26 @@ function __init__()
|
||||
@require PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee" include(joinpath(@__DIR__, "backends", "pyplot.jl"))
|
||||
@require UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" include(joinpath(@__DIR__, "backends", "unicodeplots.jl"))
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# IJulia
|
||||
# ---------------------------------------------------------
|
||||
use_local = false
|
||||
@require IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" begin
|
||||
if IJulia.inited
|
||||
# IJulia is more stable with local file
|
||||
use_local = isfile(plotly_local_file_path)
|
||||
"""
|
||||
Add extra jupyter mimetypes to display_dict based on the plot backed.
|
||||
_init_ijulia_plotting()
|
||||
|
||||
The default is nothing, except for plotly based backends, where it
|
||||
adds data for `application/vnd.plotly.v1+json` that is used in
|
||||
frontends like jupyterlab and nteract.
|
||||
"""
|
||||
_extra_mime_info!(plt::Plot, out::Dict) = out
|
||||
function _extra_mime_info!(plt::Plot{PlotlyJSBackend}, out::Dict)
|
||||
out["application/vnd.plotly.v1+json"] = JSON.lower(plt.o)
|
||||
out
|
||||
end
|
||||
|
||||
function _extra_mime_info!(plt::Plot{PlotlyBackend}, out::Dict)
|
||||
out["application/vnd.plotly.v1+json"] = Dict(
|
||||
:data => plotly_series(plt),
|
||||
:layout => plotly_layout(plt)
|
||||
)
|
||||
out
|
||||
end
|
||||
|
||||
function IJulia.display_dict(plt::Plot)
|
||||
output_type = Symbol(plt.attr[:html_output_format])
|
||||
if output_type == :auto
|
||||
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
|
||||
end
|
||||
out = Dict()
|
||||
if output_type == :txt
|
||||
mime = "text/plain"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
elseif output_type == :png
|
||||
mime = "image/png"
|
||||
out[mime] = base64encode(show, MIME(mime), plt)
|
||||
elseif output_type == :svg
|
||||
mime = "image/svg+xml"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
elseif output_type == :html
|
||||
mime = "text/html"
|
||||
out[mime] = sprint(show, MIME(mime), plt)
|
||||
else
|
||||
error("Unsupported output type $output_type")
|
||||
end
|
||||
_extra_mime_info!(plt, out)
|
||||
out
|
||||
end
|
||||
|
||||
ENV["MPLBACKEND"] = "Agg"
|
||||
IJulia.display_dict(plt::Plot) = _ijulia_display_dict(plt)
|
||||
end
|
||||
end
|
||||
|
||||
if haskey(ENV, "PLOTS_HOST_DEPENDENCY_LOCAL")
|
||||
use_local = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
|
||||
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local
|
||||
if use_local && !isfile(plotly_local_file_path)
|
||||
use_local_plotlyjs[] = ENV["PLOTS_HOST_DEPENDENCY_LOCAL"] == "true"
|
||||
use_local_dependencies[] = isfile(plotly_local_file_path) && use_local_plotlyjs[]
|
||||
if use_local_plotlyjs[] && !isfile(plotly_local_file_path)
|
||||
@warn("PLOTS_HOST_DEPENDENCY_LOCAL is set to true, but no local plotly file found. run Pkg.build(\"Plots\") and make sure PLOTS_HOST_DEPENDENCY_LOCAL is set to true")
|
||||
end
|
||||
else
|
||||
use_local_dependencies[] = use_local
|
||||
use_local_dependencies[] = use_local_plotlyjs[]
|
||||
end
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# A backup, if no PNG generation is defined, is to try to make a PDF and use FileIO to convert
|
||||
@require FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" begin
|
||||
PDFBackends = Union{PGFPlotsBackend,PlotlyJSBackend,PyPlotBackend,InspectDRBackend,GRBackend}
|
||||
function _show(io::IO, ::MIME"image/png", plt::Plot{<:PDFBackends})
|
||||
fn = tempname()
|
||||
|
||||
# first save a pdf file
|
||||
pdf(plt, fn)
|
||||
|
||||
# load that pdf into a FileIO Stream
|
||||
s = FileIO.load(fn * ".pdf")
|
||||
|
||||
# save a png
|
||||
pngfn = fn * ".png"
|
||||
FileIO.save(pngfn, s)
|
||||
|
||||
# now write from the file
|
||||
write(io, read(open(pngfn), String))
|
||||
end
|
||||
_show(io::IO, mime::MIME"image/png", plt::Plot{<:PDFBackends}) = _show_pdfbackends(io, mime, plt)
|
||||
end
|
||||
end
|
||||
|
||||
+1
-3
@@ -55,9 +55,7 @@ tex(fn::AbstractString) = tex(current(), fn)
|
||||
function html(plt::Plot, fn::AbstractString)
|
||||
fn = addExtension(fn, "html")
|
||||
io = open(fn, "w")
|
||||
_use_remote[] = true
|
||||
show(io, MIME("text/html"), plt)
|
||||
_use_remote[] = false
|
||||
close(io)
|
||||
end
|
||||
html(fn::AbstractString) = html(current(), fn)
|
||||
@@ -191,7 +189,7 @@ end
|
||||
# for writing to io streams... first prepare, then callback
|
||||
for mime in ("text/plain", "text/html", "image/png", "image/eps", "image/svg+xml",
|
||||
"application/eps", "application/pdf", "application/postscript",
|
||||
"application/x-tex")
|
||||
"application/x-tex", "application/vnd.plotly.v1+json")
|
||||
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
|
||||
if haskey(io, :juno_plotsize)
|
||||
showjuno(io, m, plt)
|
||||
|
||||
+2
-2
@@ -166,9 +166,9 @@ end
|
||||
function _plot!(plt::Plot, plotattributes::KW, args::Tuple)
|
||||
plotattributes[:plot_object] = plt
|
||||
|
||||
if !isempty(args) && !isdefined(Main, :StatPlots) &&
|
||||
if !isempty(args) && !isdefined(Main, :StatsPlots) &&
|
||||
first(split(string(typeof(args[1])), ".")) == "DataFrames"
|
||||
@warn("You're trying to plot a DataFrame, but this functionality is provided by StatPlots")
|
||||
@warn("You're trying to plot a DataFrame, but this functionality is provided by StatsPlots")
|
||||
end
|
||||
|
||||
# --------------------------------
|
||||
|
||||
+16
-8
@@ -47,7 +47,7 @@ end
|
||||
num_series(x::AMat) = size(x,2)
|
||||
num_series(x) = 1
|
||||
|
||||
RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T"))
|
||||
RecipesBase.apply_recipe(plotattributes::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T"))
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -586,12 +586,12 @@ end
|
||||
end
|
||||
Plots.@deps stepbins path
|
||||
|
||||
wand_edges(x...) = (@warn("Load the StatPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto)
|
||||
wand_edges(x...) = (@warn("Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto)
|
||||
|
||||
function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N
|
||||
_cl(x) = ceil(Int, NaNMath.max(x, one(x)))
|
||||
_cl(x) = ceil(Int, max(x, one(x)))
|
||||
_iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1))
|
||||
_span(v) = ignorenan_maximum(v) - ignorenan_minimum(v)
|
||||
_span(v) = maximum(v) - minimum(v)
|
||||
|
||||
n_samples = length(LinearIndices(first(vs)))
|
||||
|
||||
@@ -635,11 +635,19 @@ _hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abstra
|
||||
_hist_norm_mode(mode::Symbol) = mode
|
||||
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
|
||||
|
||||
_filternans(vs::NTuple{1,AbstractVector}) = filter!.(isfinite, vs)
|
||||
function _filternans(vs::NTuple{N,AbstractVector}) where N
|
||||
_invertedindex(v, not) = [j for (i,j) in enumerate(v) if !(i ∈ not)]
|
||||
nots = union(Set.(findall.(!isfinite, vs))...)
|
||||
_invertedindex.(vs, Ref(nots))
|
||||
end
|
||||
|
||||
function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
|
||||
edges = _hist_edges(vs, binning)
|
||||
localvs = _filternans(vs)
|
||||
edges = _hist_edges(localvs, binning)
|
||||
h = float( weights == nothing ?
|
||||
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
|
||||
StatsBase.fit(StatsBase.Histogram, vs, StatsBase.Weights(weights), edges, closed = :left)
|
||||
StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) :
|
||||
StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left)
|
||||
)
|
||||
normalize!(h, mode = _hist_norm_mode(normed))
|
||||
end
|
||||
@@ -1053,7 +1061,7 @@ end
|
||||
|
||||
# -------------------------------------------------
|
||||
|
||||
"Adds a+bx... straight line over the current plot, without changing the axis limits"
|
||||
"Adds ax+b... straight line over the current plot, without changing the axis limits"
|
||||
abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...)
|
||||
|
||||
abline!(args...; kw...) = abline!(current(), args...; kw...)
|
||||
|
||||
+9
-2
@@ -323,19 +323,26 @@ end
|
||||
|
||||
|
||||
# # images - grays
|
||||
function clamp_greys!(mat::AMat{T}) where T<:Gray
|
||||
for i in eachindex(mat)
|
||||
mat[i].val < 0 && (mat[i] = Gray(0))
|
||||
mat[i].val > 1 && (mat[i] = Gray(1))
|
||||
end
|
||||
mat
|
||||
end
|
||||
|
||||
@recipe function f(mat::AMat{T}) where T<:Gray
|
||||
n, m = size(mat)
|
||||
if is_seriestype_supported(:image)
|
||||
seriestype := :image
|
||||
yflip --> true
|
||||
SliceIt, 1:m, 1:n, Surface(mat)
|
||||
SliceIt, 1:m, 1:n, Surface(clamp_greys!(mat))
|
||||
else
|
||||
seriestype := :heatmap
|
||||
yflip --> true
|
||||
cbar --> false
|
||||
fillcolor --> ColorGradient([:black, :white])
|
||||
SliceIt, 1:m, 1:n, Surface(convert(Matrix{Float64}, mat))
|
||||
SliceIt, 1:m, 1:n, Surface(clamp!(convert(Matrix{Float64}, mat), 0., 1.))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,455 @@
|
||||
"""
|
||||
scatter(x,y)
|
||||
scatter!(x,y)
|
||||
|
||||
Make a scatter plot of y vs x.
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> scatter([1,2,3],[4,5,6],markersize=[3,4,5],markercolor=[:red,:green,:blue])
|
||||
julia> scatter([(1,4),(2,5),(3,6)])
|
||||
```
|
||||
"""
|
||||
@shorthands scatter
|
||||
|
||||
"""
|
||||
bar(x,y)
|
||||
bar!(x,y)
|
||||
|
||||
Make a bar plot of y vs x.
|
||||
|
||||
# Arguments
|
||||
|
||||
- $(_document_argument("bar_position"))
|
||||
- $(_document_argument("bar_width"))
|
||||
- $(_document_argument("bar_edges"))
|
||||
- $(_document_argument("orientation"))
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
julia> bar([1,2,3],[4,5,6],fillcolor=[:red,:green,:blue],fillalpha=[0.2,0.4,0.6])
|
||||
julia> bar([(1,4),(2,5),(3,6)])
|
||||
```
|
||||
"""
|
||||
@shorthands bar
|
||||
|
||||
@shorthands barh
|
||||
|
||||
"""
|
||||
histogram(x)
|
||||
histogram!(x)
|
||||
|
||||
Plot a histogram.
|
||||
|
||||
# Arguments
|
||||
|
||||
- `x`: AbstractVector of values to be binned
|
||||
- $(_document_argument("bins"))
|
||||
- `weights`: Vector of weights for the values in `x`, for weighted bin counts
|
||||
- $(_document_argument("normalize"))
|
||||
- $(_document_argument("bar_position"))
|
||||
- $(_document_argument("bar_width"))
|
||||
- $(_document_argument("bar_edges"))
|
||||
- $(_document_argument("orientation"))
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> histogram([1,2,1,1,4,3,8],bins=0:8)
|
||||
```
|
||||
"""
|
||||
@shorthands histogram
|
||||
|
||||
"""
|
||||
barhist(x)
|
||||
barhist!(x)
|
||||
|
||||
Make a histogram bar plot. See `histogram`.
|
||||
"""
|
||||
@shorthands barhist
|
||||
|
||||
"""
|
||||
stephist(x)
|
||||
stephist(x)
|
||||
|
||||
Make a histogram step plot (bin counts are represented using horizontal lines
|
||||
instead of bars). See `histogram`.
|
||||
"""
|
||||
@shorthands stephist
|
||||
|
||||
"""
|
||||
scatterhist(x)
|
||||
scatterhist!(x)
|
||||
|
||||
Make a histogram scatter plot (bin counts are represented using points
|
||||
instead of bars). See `histogram`.
|
||||
"""
|
||||
@shorthands scatterhist
|
||||
|
||||
"""
|
||||
histogram2d(x,y)
|
||||
histogram2d!(x,y)
|
||||
|
||||
Plot a two-dimensional histogram.
|
||||
|
||||
# Arguments
|
||||
|
||||
- `bins`: Number of bins (if an `Integer`) or bin edges (if an `AbtractVector`)
|
||||
- `weights`: Vector of weights for the values in `x`. Each entry of x contributes
|
||||
its weight to the height of its bin.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> histogram2d(randn(10_000),randn(10_000))
|
||||
```
|
||||
"""
|
||||
@shorthands histogram2d
|
||||
|
||||
"""
|
||||
density(x)
|
||||
density!(x)
|
||||
|
||||
Make a line plot of a kernel density estimate of x.
|
||||
|
||||
# Arguments
|
||||
|
||||
- `x`: AbstractVector of samples for probability density estimation
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> using StatsPlots
|
||||
julia> density(randn(100_000))
|
||||
```
|
||||
"""
|
||||
@shorthands density
|
||||
|
||||
"""
|
||||
heatmap(x,y,z)
|
||||
heatmap!(x,y,z)
|
||||
|
||||
Plot a heatmap of the rectangular array `z`.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> heatmap(randn(10,10))
|
||||
```
|
||||
"""
|
||||
@shorthands heatmap
|
||||
@shorthands plots_heatmap
|
||||
|
||||
"""
|
||||
hexbin(x,y)
|
||||
hexbin!(x,y)
|
||||
|
||||
Make a hexagonal binning plot (a histogram of the observations `(x[i],y[i])`
|
||||
with hexagonal bins)
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> hexbin(randn(10_000), randn(10_000))
|
||||
```
|
||||
"""
|
||||
@shorthands hexbin
|
||||
|
||||
"""
|
||||
sticks(x,y)
|
||||
sticks!(x,y)
|
||||
|
||||
Draw a stick plot of y vs x.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> sticks(1:10)
|
||||
```
|
||||
"""
|
||||
@shorthands sticks
|
||||
|
||||
"""
|
||||
hline(y)
|
||||
hline!(y)
|
||||
|
||||
Draw horizontal lines at positions specified by the values in
|
||||
the AbstractVector `y`
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> hline([-1,0,2])
|
||||
```
|
||||
"""
|
||||
@shorthands hline
|
||||
|
||||
"""
|
||||
vline(x)
|
||||
vline!(x)
|
||||
|
||||
Draw vertical lines at positions specified by the values in
|
||||
the AbstractVector `x`
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> vline([-1,0,2])
|
||||
```
|
||||
"""
|
||||
@shorthands vline
|
||||
|
||||
"""
|
||||
hspan(y)
|
||||
|
||||
Draw a rectangle between the horizontal line at position `y[1]`
|
||||
and the horizontal line at position `y[2]`. If `length(y) ≥ 4`,
|
||||
then further rectangles are drawn between `y[3]` and `y[4]`,
|
||||
`y[5]` and `y[6]`, and so on. If `length(y)` is odd, then the
|
||||
last entry of `y` is ignored.
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> hspan(1:6)
|
||||
```
|
||||
"""
|
||||
@shorthands hspan
|
||||
|
||||
"""
|
||||
vspan(x)
|
||||
|
||||
Draw a rectangle between the vertical line at position `x[1]`
|
||||
and the vertical line at position `x[2]`. If `length(x) ≥ 4`,
|
||||
then further rectangles are drawn between `x[3]` and `x[4]`,
|
||||
`x[5]` and `x[6]`, and so on. If `length(x)` is odd, then the
|
||||
last entry of `x` is ignored.
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> vspan(1:6)
|
||||
```
|
||||
"""
|
||||
@shorthands vspan
|
||||
|
||||
"""
|
||||
ohlc(x,y::Vector{OHLC})
|
||||
ohlc!(x,y::Vector{OHLC})
|
||||
|
||||
Make open-high-low-close plot. Each entry of y is represented by a vertical
|
||||
segment extending from the low value to the high value, with short horizontal
|
||||
segments on the left and right indicating the open and close values, respectively.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> meanprices = cumsum(randn(100))
|
||||
julia> y = OHLC[(p+rand(),p+1,p-1,p+rand()) for p in meanprices]
|
||||
julia> ohlc(y)
|
||||
```
|
||||
"""
|
||||
@shorthands ohlc
|
||||
|
||||
|
||||
"""
|
||||
contour(x,y,z)
|
||||
contour!(x,y,z)
|
||||
|
||||
Draw contour lines of the `Surface` z.
|
||||
|
||||
# Arguments
|
||||
- `levels`: Contour levels (if `AbstractVector`) or number of levels (if `Integer`)
|
||||
- `fill`: Bool. Fill area between contours or draw contours only (false by default)
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> x = y = range(-20, 20, length = 100)
|
||||
julia> contour(x, y, (x, y) -> x^2 + y^2)
|
||||
```
|
||||
"""
|
||||
@shorthands contour
|
||||
|
||||
"An alias for `contour` with fill = true."
|
||||
@shorthands contourf
|
||||
|
||||
|
||||
@shorthands contour3d
|
||||
|
||||
"""
|
||||
surface(x,y,z)
|
||||
surface!(x,y,z)
|
||||
|
||||
Draw a 3D surface plot.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> x = y = range(-3, 3, length = 100)
|
||||
julia> surface(x, y, (x, y) -> sinc(norm([x, y])))
|
||||
```
|
||||
"""
|
||||
@shorthands surface
|
||||
|
||||
"""
|
||||
wireframe(x,y,z)
|
||||
wireframe!(x,y,z)
|
||||
|
||||
Draw a 3D wireframe plot.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> wireframe(1:10,1:10,randn(10,10))
|
||||
```
|
||||
"""
|
||||
@shorthands wireframe
|
||||
|
||||
"""
|
||||
path3d(x,y,z)
|
||||
path3d!(x,y,z)
|
||||
|
||||
Plot a 3D path from `(x[1],y[1],z[1])` to `(x[2],y[2],z[2])`,
|
||||
..., to `(x[end],y[end],z[end])`.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> path3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
|
||||
```
|
||||
"""
|
||||
@shorthands path3d
|
||||
|
||||
"""
|
||||
scatter3d(x,y,z)
|
||||
scatter3d!(x,y,z)
|
||||
|
||||
Make a 3D scatter plot.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> scatter3d([0,1,2,3],[0,1,4,9],[0,1,8,27])
|
||||
```
|
||||
"""
|
||||
@shorthands scatter3d
|
||||
|
||||
"""
|
||||
boxplot(x, y)
|
||||
boxplot!(x, y)
|
||||
|
||||
Make a box and whisker plot.
|
||||
|
||||
# Keyword arguments
|
||||
- `notch`: Bool. Notch the box plot? (false)
|
||||
- `range`: Real. Values more than range*IQR below the first quartile
|
||||
or above the third quartile are shown as outliers (1.5)
|
||||
- `outliers`: Bool. Show outliers? (true)
|
||||
- `whisker_width`: Real or Symbol. Length of whiskers (:match)
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> using StatsPlots
|
||||
julia> boxplot(repeat([1,2,3],outer=100),randn(300))
|
||||
```
|
||||
"""
|
||||
@shorthands boxplot
|
||||
|
||||
"""
|
||||
violin(x,y,z)
|
||||
violin!(x,y,z)
|
||||
|
||||
Make a violin plot.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> violin(repeat([1,2,3],outer=100),randn(300))
|
||||
```
|
||||
"""
|
||||
@shorthands violin
|
||||
|
||||
"""
|
||||
quiver(x,y,quiver=(u,v))
|
||||
quiver!(x,y,quiver=(u,v))
|
||||
|
||||
Make a quiver (vector field) plot. The `i`th vector extends
|
||||
from `(x[i],y[i])` to `(x[i] + u[i], y[i] + v[i])`.
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3]))
|
||||
```
|
||||
"""
|
||||
@shorthands quiver
|
||||
|
||||
"""
|
||||
curves(x,y)
|
||||
curves!(x,y)
|
||||
|
||||
Draw a Bezier curve from `(x[1],y[1])` to `(x[end],y[end])`
|
||||
with control points `(x[2],y[2]), ..., (x[end-1],y[end]-1)`
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> curves([1,2,3,4],[1,1,2,4])
|
||||
```
|
||||
"""
|
||||
@shorthands curves
|
||||
|
||||
"Plot a pie diagram"
|
||||
pie(args...; kw...) = plot(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
|
||||
pie!(args...; kw...) = plot!(args...; kw..., seriestype = :pie, aspect_ratio = :equal, grid=false, xticks=nothing, yticks=nothing)
|
||||
|
||||
"Plot with seriestype :path3d"
|
||||
plot3d(args...; kw...) = plot(args...; kw..., seriestype = :path3d)
|
||||
plot3d!(args...; kw...) = plot!(args...; kw..., seriestype = :path3d)
|
||||
|
||||
"Add title to an existing plot"
|
||||
title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
|
||||
|
||||
"Add xlabel to an existing plot"
|
||||
xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
|
||||
|
||||
"Add ylabel to an existing plot"
|
||||
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
|
||||
|
||||
"Set xlims for an existing plot"
|
||||
xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...)
|
||||
|
||||
"Set ylims for an existing plot"
|
||||
ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...)
|
||||
|
||||
"Set zlims for an existing plot"
|
||||
zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...)
|
||||
|
||||
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
|
||||
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
|
||||
zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmin,zmax), kw...)
|
||||
|
||||
|
||||
"Set xticks for an existing plot"
|
||||
xticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
|
||||
|
||||
"Set yticks for an existing plot"
|
||||
yticks!(v::TicksArgs; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
|
||||
|
||||
xticks!(
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
|
||||
yticks!(
|
||||
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...)
|
||||
|
||||
"""
|
||||
annotate!(anns...)
|
||||
|
||||
Add annotations to an existing plot.
|
||||
|
||||
# Arguments
|
||||
|
||||
- `anns`: An `AbstractVector` of tuples of the form (x,y,text). The text object
|
||||
can be an String or PlotText
|
||||
|
||||
# Example
|
||||
```julia-repl
|
||||
julia> plot(1:10)
|
||||
julia> annotate!([(7,3,"(7,3)"),(3,7,text("hey", 14, :left, :top, :green))])
|
||||
```
|
||||
"""
|
||||
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
|
||||
annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...)
|
||||
|
||||
"Flip the current plots' x axis"
|
||||
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
|
||||
|
||||
"Flip the current plots' y axis"
|
||||
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
|
||||
|
||||
"Specify x axis attributes for an existing plot"
|
||||
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
|
||||
|
||||
"Specify x axis attributes for an existing plot"
|
||||
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
|
||||
xgrid!(args...; kw...) = plot!(; xgrid = args, kw...)
|
||||
ygrid!(args...; kw...) = plot!(; ygrid = args, kw...)
|
||||
+52
-2
@@ -431,7 +431,7 @@ isvertical(series::Series) = isvertical(series.plotattributes)
|
||||
|
||||
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
|
||||
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
|
||||
ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels
|
||||
ticksType(ticks::Tuple{T,S}) where {T<:Union{AVec,Tuple},S<:Union{AVec,Tuple}} = :ticks_and_labels
|
||||
ticksType(ticks) = :invalid
|
||||
|
||||
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
|
||||
@@ -610,6 +610,22 @@ function hascolorbar(sp::Subplot)
|
||||
hascbar
|
||||
end
|
||||
|
||||
function colorbar_levels(series::Series, clims)
|
||||
if series[:seriestype] == :contour
|
||||
zmin, zmax = clims
|
||||
levels = series[:levels]
|
||||
levels isa AbstractArray ?
|
||||
levels :
|
||||
levels > 1 ?
|
||||
range(zmin, stop=zmax, length=levels) :
|
||||
[(zmin + zmax) / 2]
|
||||
else # including heatmap, surface
|
||||
nothing
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
for comp in (:line, :fill, :marker)
|
||||
|
||||
compcolor = string(comp, :color)
|
||||
@@ -726,7 +742,7 @@ function with(f::Function, args...; kw...)
|
||||
|
||||
# save the backend
|
||||
if CURRENT_BACKEND.sym == :none
|
||||
pickDefaultBackend()
|
||||
_pick_default_backend()
|
||||
end
|
||||
oldbackend = CURRENT_BACKEND.sym
|
||||
|
||||
@@ -1199,3 +1215,37 @@ end
|
||||
function construct_categorical_data(x::AbstractArray, axis::Axis)
|
||||
map(xi -> axis[:discrete_values][searchsortedfirst(axis[:continuous_values], xi)], x)
|
||||
end
|
||||
|
||||
_fmt_paragraph(paragraph::AbstractString;kwargs...) = _fmt_paragraph(IOBuffer(),paragraph,0;kwargs...)
|
||||
|
||||
function _fmt_paragraph(io::IOBuffer,
|
||||
remaining_text::AbstractString,
|
||||
column_count::Integer;
|
||||
fillwidth=60,
|
||||
leadingspaces=0)
|
||||
|
||||
kwargs = (fillwidth = fillwidth, leadingspaces = leadingspaces)
|
||||
|
||||
m = match(r"(.*?) (.*)",remaining_text)
|
||||
if isa(m,Nothing)
|
||||
if column_count + length(remaining_text) ≤ fillwidth
|
||||
print(io,remaining_text)
|
||||
String(take!(io))
|
||||
else
|
||||
print(io,"\n"*" "^leadingspaces*remaining_text)
|
||||
String(take!(io))
|
||||
end
|
||||
else
|
||||
if column_count + length(m[1]) ≤ fillwidth
|
||||
print(io,"$(m[1]) ")
|
||||
_fmt_paragraph(io,m[2],column_count + length(m[1]) + 1;kwargs...)
|
||||
else
|
||||
print(io,"\n"*" "^leadingspaces*"$(m[1]) ")
|
||||
_fmt_paragraph(io,m[2],leadingspaces;kwargs...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _document_argument(S::AbstractString)
|
||||
_fmt_paragraph("`$S`: "*_arg_desc[Symbol(S)],leadingspaces = 6 + length(S))
|
||||
end
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
StatPlots
|
||||
StatsPlots
|
||||
Images
|
||||
ImageMagick
|
||||
@osx QuartzImageIO
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ end
|
||||
|
||||
|
||||
using Plots
|
||||
# using StatPlots
|
||||
# using StatsPlots
|
||||
import PlotReferenceImages
|
||||
using Random
|
||||
using Test
|
||||
|
||||
+6
-1
@@ -33,7 +33,12 @@ end
|
||||
@test backend() == Plots.UnicodePlotsBackend()
|
||||
|
||||
# lets just make sure it runs without error
|
||||
@test isa(plot(rand(10)), Plots.Plot) == true
|
||||
p = plot(rand(10))
|
||||
@test isa(p, Plots.Plot) == true
|
||||
@test isa(display(p), Nothing) == true
|
||||
p = bar(randn(10))
|
||||
@test isa(p, Plots.Plot) == true
|
||||
@test isa(display(p), Nothing) == true
|
||||
end
|
||||
|
||||
# The plotlyjs testimages return a connection error on travis:
|
||||
|
||||
Reference in New Issue
Block a user