Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 45a04d5309 | |||
| 6420f6fdc9 | |||
| 19a9726e61 |
@@ -3,47 +3,14 @@
|
||||
|
||||
#### notes on release changes, ongoing development, and future planned work
|
||||
|
||||
- All new development should target 0.12!
|
||||
- Minor version 0.11 is the last one to support Julia 0.5!!
|
||||
- All new development should target 0.9!
|
||||
- Minor version 0.8 is the last one to support Julia 0.4!!
|
||||
- Critical bugfixes only
|
||||
- `backports` branch is for Julia 0.4
|
||||
|
||||
---
|
||||
|
||||
## 0.11 (current master/dev)
|
||||
|
||||
#### 0.11.0
|
||||
|
||||
- julia 0.6 compatibility
|
||||
- matplotlib 0.2.0 compatibility
|
||||
- add inspectdr backend
|
||||
- improved histogram functionality:
|
||||
- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default)
|
||||
- support for log scale axes with histograms
|
||||
- support for plotting `StatsBase.Histogram`
|
||||
- allowing bins to be specified as `:sturges`, `:rice`, `:scott` or :fd
|
||||
- allow `normalization` to be specified as :density (for unequal bins) or :pdf (sum to 1)
|
||||
- add a `plotattr` function to access documentation for Plots attribute
|
||||
- add `fill_z` attribute for pyplot
|
||||
- add colorbar_title to plotlyjs
|
||||
- enable standalone window for plotlyjs
|
||||
- improved support for pgfplots, ticks rotation, clims, series_annotations
|
||||
- restore colorbars for GR
|
||||
- better axis labels for heatmap in GR
|
||||
- better marker sizes in GR
|
||||
- fix color representation in GR
|
||||
- update GR legend
|
||||
- fix image bug on GR
|
||||
- fix glvisualize dependencies
|
||||
- set dotted grid lines for pyplot
|
||||
- several improvements to inspectdr
|
||||
- improved tick positions for TimeType x axes
|
||||
- support for improved color gradient capability in PlotUtils
|
||||
- add a showlibrary recipe to display color libraries
|
||||
- add a showgradient recipe to display color gradients
|
||||
- add `vectorfield` as an alias for `quiver`
|
||||
- use `PlotUtils.adaptedgrid` for functions
|
||||
|
||||
## 0.9 (current master/dev)
|
||||
|
||||
#### 0.9.5
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Plots
|
||||
|
||||
[](https://travis-ci.org/JuliaPlots/Plots.jl)
|
||||
[](https://travis-ci.org/tbreloff/Plots.jl)
|
||||
[](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
|
||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
|
||||
|
||||
@@ -7,4 +7,4 @@ Reexport
|
||||
FixedSizeArrays
|
||||
Measures
|
||||
Showoff
|
||||
StatsBase 0.14.0
|
||||
StatsBase
|
||||
|
||||
+1
-2
@@ -80,8 +80,7 @@ function buildanimation(animdir::AbstractString, fn::AbstractString;
|
||||
|
||||
catch err
|
||||
warn("""Tried to create gif using convert (ImageMagick), but got error: $err
|
||||
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`.
|
||||
You may also need to install the imagemagick c++ library through your operating system.
|
||||
ImageMagick can be installed by executing `Pkg.add("ImageMagick")`
|
||||
Will try ffmpeg, but it's lower quality...)""")
|
||||
|
||||
# low quality
|
||||
|
||||
+2
-2
@@ -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. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)",
|
||||
:bins => "Integer, NTuple{2,Integer}, AbstractVector. For histogram-types, defines the number of bins, or the edges, of the histogram.",
|
||||
: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",
|
||||
@@ -40,7 +40,7 @@ const _arg_desc = KW(
|
||||
: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.",
|
||||
:arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.",
|
||||
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a PDF with integral of 1) and :density (only normalize in respect to bin sizes).",
|
||||
:normalize => "Bool. Should normalize histogram types? Trying for area == 1.",
|
||||
:weights => "AbstractVector. Used in histogram types for weighted counts.",
|
||||
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
|
||||
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
|
||||
|
||||
+4
-9
@@ -35,9 +35,7 @@ const _3dTypes = [
|
||||
]
|
||||
const _allTypes = vcat([
|
||||
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
||||
:heatmap, :hexbin, :barbins, :barhist, :histogram, :scatterbins,
|
||||
:scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :histogram3d,
|
||||
:density, :bar, :hline, :vline,
|
||||
:heatmap, :hexbin, :histogram, :histogram2d, :histogram3d, :density, :bar, :hline, :vline,
|
||||
:contour, :pie, :shape, :image
|
||||
], _3dTypes)
|
||||
|
||||
@@ -67,7 +65,6 @@ const _typeAliases = Dict{Symbol,Symbol}(
|
||||
:polygon => :shape,
|
||||
:box => :boxplot,
|
||||
:velocity => :quiver,
|
||||
:vectorfield => :quiver,
|
||||
:gradient => :quiver,
|
||||
:img => :image,
|
||||
:imshow => :image,
|
||||
@@ -80,7 +77,7 @@ const _typeAliases = Dict{Symbol,Symbol}(
|
||||
|
||||
add_non_underscore_aliases!(_typeAliases)
|
||||
|
||||
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins)
|
||||
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins, :density)
|
||||
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
|
||||
like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image)
|
||||
|
||||
@@ -156,8 +153,6 @@ const _markerAliases = Dict{Symbol,Symbol}(
|
||||
)
|
||||
|
||||
const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
|
||||
const _logScales = [:ln, :log2, :log10]
|
||||
const _logScaleBases = Dict(:ln => e, :log2 => 2.0, :log10 => 10.0)
|
||||
const _scaleAliases = Dict{Symbol,Symbol}(
|
||||
:none => :identity,
|
||||
:log => :log10,
|
||||
@@ -185,7 +180,7 @@ const _series_defaults = KW(
|
||||
:markerstrokewidth => 1,
|
||||
:markerstrokecolor => :match,
|
||||
:markerstrokealpha => nothing,
|
||||
:bins => :auto, # number of bins for hists
|
||||
:bins => 30, # number of bins for hists
|
||||
:smooth => false, # regression line?
|
||||
:group => nothing, # groupby vector
|
||||
:x => nothing,
|
||||
@@ -450,7 +445,7 @@ add_aliases(:color_palette, :palette)
|
||||
add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse)
|
||||
add_aliases(:xerror, :xerr, :xerrorbar)
|
||||
add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar)
|
||||
add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield)
|
||||
add_aliases(:quiver, :velocity, :quiver2d, :gradient)
|
||||
add_aliases(:normalize, :norm, :normed, :normalized)
|
||||
add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio)
|
||||
add_aliases(:match_dimensions, :transpose, :transpose_z)
|
||||
|
||||
+1
-25
@@ -156,30 +156,6 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing)
|
||||
scale = axis[:scale]
|
||||
sf = scalefunc(scale)
|
||||
|
||||
# If the axis input was a Date or DateTime use a special logic to find
|
||||
# "round" Date(Time)s as ticks
|
||||
# This bypasses the rest of optimal_ticks_and_labels, because
|
||||
# optimize_datetime_ticks returns ticks AND labels: the label format (Date
|
||||
# or DateTime) is chosen based on the time span between amin and amax
|
||||
# rather than on the input format
|
||||
# TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime
|
||||
if ticks == nothing && scale == :identity
|
||||
if axis[:formatter] == dateformatter
|
||||
# optimize_datetime_ticks returns ticks and labels(!) based on
|
||||
# integers/floats corresponding to the DateTime type. Thus, the axes
|
||||
# limits, which resulted from converting the Date type to integers,
|
||||
# are converted to 'DateTime integers' (actually floats) before
|
||||
# being passed to optimize_datetime_ticks.
|
||||
# (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i)
|
||||
ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax;
|
||||
k_min = 2, k_max = 4)
|
||||
# Now the ticks are converted back to floats corresponding to Dates.
|
||||
return ticks / 864e5, labels
|
||||
elseif axis[:formatter] == datetimeformatter
|
||||
return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4)
|
||||
end
|
||||
end
|
||||
|
||||
# get a list of well-laid-out ticks
|
||||
scaled_ticks = if ticks == nothing
|
||||
optimize_ticks(
|
||||
@@ -238,7 +214,7 @@ function get_ticks(axis::Axis)
|
||||
# @show ticks dvals cv dv
|
||||
|
||||
# TODO: better/smarter cutoff values for sampling ticks
|
||||
if length(cv) > 30 && ticks == :auto
|
||||
if length(cv) > 30
|
||||
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
||||
cv[rng], dv[rng]
|
||||
else
|
||||
|
||||
+14
-13
@@ -1,4 +1,4 @@
|
||||
#=
|
||||
``#=
|
||||
TODO
|
||||
* move all gl_ methods to GLPlot
|
||||
* integrate GLPlot UI
|
||||
@@ -7,6 +7,7 @@ TODO
|
||||
* polar plots
|
||||
* labes and axis
|
||||
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
|
||||
* why is there so little unicode supported in the font!??!?
|
||||
=#
|
||||
|
||||
const _glvisualize_attr = merge_with_base_supported([
|
||||
@@ -133,6 +134,11 @@ function empty_screen!(screen)
|
||||
end
|
||||
nothing
|
||||
end
|
||||
function poll_reactive()
|
||||
# run_till_now blocks when message queue is empty!
|
||||
Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now()
|
||||
end
|
||||
|
||||
|
||||
function get_plot_screen(list::Vector, name, result = [])
|
||||
for elem in list
|
||||
@@ -149,20 +155,19 @@ function get_plot_screen(screen, name, result = [])
|
||||
end
|
||||
|
||||
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
||||
name = Symbol("__Plots.jl")
|
||||
name = Symbol("Plots.jl")
|
||||
# make sure we have any screen open
|
||||
if isempty(GLVisualize.get_screens())
|
||||
# create a fresh, new screen
|
||||
parent_screen = GLVisualize.glscreen(
|
||||
"Plots",
|
||||
"Plot",
|
||||
resolution = plt[:size],
|
||||
visible = visible
|
||||
)
|
||||
@async GLWindow.waiting_renderloop(parent_screen)
|
||||
GLVisualize.add_screen(parent_screen)
|
||||
end
|
||||
# now lets get ourselves a permanent Plotting screen
|
||||
plot_screens = get_plot_screen(GLVisualize.current_screen(), name)
|
||||
plot_screens = get_plot_screen(GLVisualize.get_screens(), name)
|
||||
screen = if isempty(plot_screens) # no screen with `name`
|
||||
parent = GLVisualize.current_screen()
|
||||
screen = GLWindow.Screen(
|
||||
@@ -178,7 +183,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
||||
else
|
||||
# okay this is silly! Lets see if we can. There is an ID we could use
|
||||
# will not be fine for more than 255 screens though -.-.
|
||||
error("multiple Plot screens. Please don't use any screen with the name $name")
|
||||
error("multiple Plot screens. Please don't use any screen with the name Plots.jl")
|
||||
end
|
||||
# Since we own this window, we can do deep cleansing
|
||||
empty_screen!(screen)
|
||||
@@ -1136,7 +1141,8 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
|
||||
vis = gl_bar(d, kw_args)
|
||||
elseif st == :image
|
||||
extract_extrema(d, kw_args)
|
||||
vis = GL.gl_image(d[:z].surf, kw_args)
|
||||
z = transpose_z(series, d[:z].surf, false)
|
||||
vis = GL.gl_image(z, kw_args)
|
||||
elseif st == :boxplot
|
||||
extract_c(d, kw_args, :fill)
|
||||
vis = gl_boxplot(d, kw_args)
|
||||
@@ -1176,7 +1182,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true)
|
||||
if _3d
|
||||
GLAbstraction.center!(sp_screen)
|
||||
end
|
||||
GLAbstraction.post_empty()
|
||||
Reactive.post_empty()
|
||||
yield()
|
||||
end
|
||||
end
|
||||
@@ -1416,8 +1422,6 @@ function label_scatter(d, w, ho)
|
||||
color = get(kw, :color, nothing)
|
||||
kw[:color] = isa(color, Array) ? first(color) : color
|
||||
end
|
||||
strcolor = get(kw, :stroke_color, RGBA{Float32}(0,0,0,0))
|
||||
kw[:stroke_color] = isa(strcolor, Array) ? first(strcolor) : strcolor
|
||||
p = get(kw, :primitive, GeometryTypes.Circle)
|
||||
if isa(p, GLNormalMesh)
|
||||
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
|
||||
@@ -1432,9 +1436,6 @@ function label_scatter(d, w, ho)
|
||||
kw[:scale] = Vec3f0(w/2)
|
||||
delete!(kw, :offset)
|
||||
end
|
||||
if isa(p, Array)
|
||||
kw[:primitive] = GeometryTypes.Circle
|
||||
end
|
||||
GL.gl_scatter(Point2f0[(w/2, ho)], kw)
|
||||
end
|
||||
|
||||
|
||||
+11
-18
@@ -172,8 +172,6 @@ function gr_polyline(x, y, func = GR.polyline; arrowside=:none)
|
||||
end
|
||||
end
|
||||
|
||||
gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s))
|
||||
|
||||
function gr_inqtext(x, y, s)
|
||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||
GR.inqtextext(x, y, s[2:end-1])
|
||||
@@ -184,8 +182,6 @@ function gr_inqtext(x, y, s)
|
||||
end
|
||||
end
|
||||
|
||||
gr_text(x, y, s::Symbol) = gr_text(x, y, string(s))
|
||||
|
||||
function gr_text(x, y, s)
|
||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||
GR.mathtex(x, y, s[2:end-1])
|
||||
@@ -287,8 +283,7 @@ end
|
||||
# draw ONE symbol marker
|
||||
function gr_draw_marker(xi, yi, msize::Number, shape::Symbol)
|
||||
GR.setmarkertype(gr_markertype[shape])
|
||||
w, h = gr_plot_size
|
||||
GR.setmarkersize(0.3msize / ((w + h) * 0.001))
|
||||
GR.setmarkersize(0.3msize)
|
||||
GR.polymarker([xi], [yi])
|
||||
end
|
||||
|
||||
@@ -335,10 +330,9 @@ end
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
function gr_set_line(lw, style, c) #, a)
|
||||
function gr_set_line(w, style, c) #, a)
|
||||
GR.setlinetype(gr_linetype[style])
|
||||
w, h = gr_plot_size
|
||||
GR.setlinewidth(max(0, lw / ((w + h) * 0.001)))
|
||||
GR.setlinewidth(w)
|
||||
gr_set_linecolor(c) #, a)
|
||||
end
|
||||
|
||||
@@ -427,7 +421,7 @@ end
|
||||
function gr_colorbar(sp::Subplot)
|
||||
if sp[:colorbar] != :none
|
||||
gr_set_viewport_cmap(sp)
|
||||
GR.colorbar()
|
||||
GR.colormap()
|
||||
gr_set_viewport_plotarea()
|
||||
end
|
||||
end
|
||||
@@ -551,10 +545,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
if st == :heatmap
|
||||
outside_ticks = true
|
||||
x, y = heatmap_edges(series[:x]), heatmap_edges(series[:y])
|
||||
expand_extrema!(sp[:xaxis], x)
|
||||
expand_extrema!(sp[:yaxis], y)
|
||||
data_lims = gr_xy_axislims(sp)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -769,6 +759,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
# recompute data
|
||||
if typeof(z) <: Surface
|
||||
# if st == :heatmap
|
||||
# expand_extrema!(sp[:xaxis], (x[1]-0.5*(x[2]-x[1]), x[end]+0.5*(x[end]-x[end-1])))
|
||||
# expand_extrema!(sp[:yaxis], (y[1]-0.5*(y[2]-y[1]), y[end]+0.5*(y[end]-y[end-1])))
|
||||
# end
|
||||
z = vec(transpose_z(series, z.surf, false))
|
||||
elseif ispolar(sp)
|
||||
if frng != nothing
|
||||
@@ -813,12 +807,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
end
|
||||
GR.setspace(zmin, zmax, 0, 90)
|
||||
if typeof(series[:levels]) <: Array
|
||||
h = series[:levels]
|
||||
else
|
||||
h = linspace(zmin, zmax, series[:levels])
|
||||
end
|
||||
GR.setspace(zmin, zmax, 0, 90)
|
||||
if series[:fillrange] != nothing
|
||||
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
||||
else
|
||||
@@ -856,7 +850,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
isfinite(clims[1]) && (zmin = clims[1])
|
||||
isfinite(clims[2]) && (zmax = clims[2])
|
||||
end
|
||||
GR.setspace(zmin, zmax, 0, 90)
|
||||
grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad()
|
||||
colors = [grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)] for zi=z]
|
||||
rgba = map(c -> UInt32( round(Int, alpha(c) * 255) << 24 +
|
||||
@@ -951,7 +944,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
|
||||
elseif st == :image
|
||||
z = transpose_z(series, series[:z].surf, true)
|
||||
w, h = size(z)
|
||||
h, w = size(z)
|
||||
if eltype(z) <: Colors.AbstractGray
|
||||
grey = round(UInt8, float(z) * 255)
|
||||
rgba = map(c -> UInt32( 0xff000000 + Int(c)<<16 + Int(c)<<8 + Int(c) ), grey)
|
||||
@@ -1110,7 +1103,7 @@ function _display(plt::Plot{GRBackend})
|
||||
ENV["GKS_FILEPATH"] = filepath
|
||||
gr_display(plt)
|
||||
GR.emergencyclosegks()
|
||||
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(read, filepath)), "\a")
|
||||
content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(readbytes, filepath)), "\a")
|
||||
println(content)
|
||||
rm(filepath)
|
||||
else
|
||||
|
||||
@@ -213,10 +213,14 @@ end
|
||||
# Set up the subplot within the backend object.
|
||||
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
|
||||
plot = sp.o
|
||||
|
||||
#Don't do anything without a "subplot" object: Will process later.
|
||||
if nothing == plot; return; end
|
||||
plot.data = []
|
||||
plot.userannot = [] #Clear old markers/text annotation/polyline "annotation"
|
||||
plot.markers = [] #Clear old markers
|
||||
plot.atext = [] #Clear old annotation
|
||||
plot.apline = [] #Clear old poly lines
|
||||
|
||||
return plot
|
||||
end
|
||||
|
||||
@@ -273,7 +277,7 @@ For st in :shape:
|
||||
apline = InspectDR.PolylineAnnotation(
|
||||
x[rng], y[rng], line=line, fillcolor=fillcolor
|
||||
)
|
||||
InspectDR.add(plot, apline)
|
||||
push!(plot.apline, apline)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -411,6 +415,8 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend})
|
||||
plot = sp.o
|
||||
_initialize_subplot(plt, sp)
|
||||
_inspectdr_setupsubplot(sp)
|
||||
graphbb = _inspectdr_to_pixels(plotarea(sp))
|
||||
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
|
||||
|
||||
# add the annotations
|
||||
for ann in sp[:annotations]
|
||||
@@ -465,11 +471,7 @@ function _update_plot_object(plt::Plot{InspectDRBackend})
|
||||
mplot = _inspectdr_getmplot(plt.o)
|
||||
if nothing == mplot; return; end
|
||||
|
||||
for (i, sp) in enumerate(plt.subplots)
|
||||
graphbb = _inspectdr_to_pixels(plotarea(sp))
|
||||
plot = mplot.subplots[i]
|
||||
plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb)
|
||||
end
|
||||
#TODO: should plotbb be computed here??
|
||||
|
||||
gplot = _inspectdr_getgui(plt.o)
|
||||
if nothing == gplot; return; end
|
||||
|
||||
@@ -22,8 +22,8 @@ const _pgfplots_attr = merge_with_base_supported([
|
||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||
:tickfont, :guidefont, :legendfont,
|
||||
:grid, :legend,
|
||||
:colorbar,
|
||||
:marker_z, #:levels,
|
||||
# :colorbar,
|
||||
# :marker_z, :levels,
|
||||
# :ribbon, :quiver, :arrow,
|
||||
# :orientation,
|
||||
# :overwrite_figure,
|
||||
@@ -98,8 +98,6 @@ const _pgf_series_extrastyle = KW(
|
||||
:xsticks => "xcomb",
|
||||
)
|
||||
|
||||
# PGFPlots uses the anchors to define orientations for example to align left
|
||||
# one needs to use the right edge as anchor
|
||||
const _pgf_annotation_halign = KW(
|
||||
:center => "",
|
||||
:left => "right",
|
||||
@@ -109,24 +107,11 @@ const _pgf_annotation_halign = KW(
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
# takes in color,alpha, and returns color and alpha appropriate for pgf style
|
||||
function pgf_color(c::Colorant)
|
||||
function pgf_color(c)
|
||||
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c))
|
||||
cstr, alpha(c)
|
||||
end
|
||||
|
||||
function pgf_color(grad::ColorGradient)
|
||||
# Can't handle ColorGradient here, fallback to defaults.
|
||||
cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012)
|
||||
cstr, 1
|
||||
end
|
||||
|
||||
# Generates a colormap for pgfplots based on a ColorGradient
|
||||
function pgf_colormap(grad::ColorGradient)
|
||||
join(map(grad.colors) do c
|
||||
@sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c))
|
||||
end,", ")
|
||||
end
|
||||
|
||||
function pgf_fillstyle(d::KW)
|
||||
cstr,a = pgf_color(d[:fillcolor])
|
||||
"fill = $cstr, fill opacity=$a"
|
||||
@@ -177,6 +162,7 @@ function pgf_series(sp::Subplot, series::Series)
|
||||
st = d[:seriestype]
|
||||
style = []
|
||||
kw = KW()
|
||||
|
||||
push!(style, pgf_linestyle(d))
|
||||
push!(style, pgf_marker(d))
|
||||
|
||||
@@ -196,10 +182,6 @@ function pgf_series(sp::Subplot, series::Series)
|
||||
d[:z].surf, d[:x], d[:y]
|
||||
elseif is3d(st)
|
||||
d[:x], d[:y], d[:z]
|
||||
elseif d[:marker_z] != nothing
|
||||
# If a marker_z is used pass it as third coordinate to a 2D plot.
|
||||
# See "Scatter Plots" in PGFPlots documentation
|
||||
d[:x], d[:y], d[:marker_z]
|
||||
else
|
||||
d[:x], d[:y]
|
||||
end
|
||||
@@ -292,7 +274,6 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
||||
# Obtain the total height of the plot by extracting the maximal bottom
|
||||
# coordinate from the bounding box.
|
||||
total_height = bottom(bbox(plt.layout))
|
||||
|
||||
for sp in plt.subplots
|
||||
# first build the PGFPlots.Axis object
|
||||
style = ["unbounded coords=jump"]
|
||||
@@ -338,34 +319,6 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
||||
if sp[:projection] == :polar
|
||||
axisf = PGFPlots.PolarAxis
|
||||
end
|
||||
|
||||
# Search series for any gradient. In case one series uses a gradient set
|
||||
# the colorbar and colomap.
|
||||
# The reasoning behind doing this on the axis level is that pgfplots
|
||||
# colorbar seems to only works on axis level and needs the proper colormap for
|
||||
# correctly displaying it.
|
||||
# It's also possible to assign the colormap to the series itself but
|
||||
# then the colormap needs to be added twice, once for the axis and once for the
|
||||
# series.
|
||||
# As it is likely that all series within the same axis use the same
|
||||
# colormap this should not cause any problem.
|
||||
for series in series_list(sp)
|
||||
for col in (:markercolor, :fillcolor)
|
||||
if typeof(series.d[col]) == ColorGradient
|
||||
push!(style,"colormap={plots}{$(pgf_colormap(series.d[col]))}")
|
||||
|
||||
if sp[:colorbar] == :none
|
||||
kw[:colorbar] = "false"
|
||||
else
|
||||
kw[:colorbar] = "true"
|
||||
end
|
||||
# goto is needed to break out of col and series for
|
||||
@goto colorbar_end
|
||||
end
|
||||
end
|
||||
end
|
||||
@label colorbar_end
|
||||
|
||||
o = axisf(; style = style, kw...)
|
||||
|
||||
# add the series object to the PGFPlots.Axis
|
||||
|
||||
+4
-14
@@ -19,7 +19,7 @@ const _plotly_attr = merge_with_base_supported([
|
||||
:window_title,
|
||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||
:tickfont, :guidefont, :legendfont,
|
||||
:grid, :legend, :colorbar, :colorbar_title,
|
||||
:grid, :legend, :colorbar,
|
||||
:marker_z, :fill_z, :levels,
|
||||
:ribbon, :quiver,
|
||||
:orientation,
|
||||
@@ -269,7 +269,7 @@ function plotly_layout(plt::Plot)
|
||||
w, h = plt[:size]
|
||||
d_out[:width], d_out[:height] = w, h
|
||||
d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside])
|
||||
d_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20)
|
||||
d_out[:margin] = KW(:l=>0, :b=>0, :r=>0, :t=>20)
|
||||
|
||||
d_out[:annotations] = KW[]
|
||||
|
||||
@@ -409,13 +409,6 @@ plotly_surface_data(series::Series, a::AbstractVector) = a
|
||||
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
|
||||
plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf)
|
||||
|
||||
#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z)
|
||||
as_gradient(grad::ColorGradient, α) = grad
|
||||
as_gradient(grad, α) = cgrad(alpha = α)
|
||||
|
||||
# allows passing a ColorGradient where a single color is expected - the other backends allow this
|
||||
PlotUtils.rgba_string(cg::ColorGradient) = rgba_string(cg[1])
|
||||
|
||||
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
||||
function plotly_series(plt::Plot, series::Series)
|
||||
st = series[:seriestype]
|
||||
@@ -446,8 +439,6 @@ function plotly_series(plt::Plot, series::Series)
|
||||
end
|
||||
end
|
||||
|
||||
d_out[:colorbar] = KW(:title => sp[:colorbar_title])
|
||||
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
d_out[:zmin], d_out[:zmax] = clims
|
||||
@@ -548,10 +539,9 @@ function plotly_series(plt::Plot, series::Series)
|
||||
rgba_string(series[:markercolor])
|
||||
else
|
||||
# grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha])
|
||||
grad = as_gradient(series[:markercolor], series[:markeralpha])
|
||||
grad = series[:markercolor]
|
||||
zmin, zmax = extrema(series[:marker_z])
|
||||
zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line)
|
||||
[rgba_string(grad[(zi - zmin) / zrange]) for zi in series[:marker_z]]
|
||||
[rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+14
-9
@@ -85,7 +85,17 @@ function _initialize_backend(::PyPlotBackend)
|
||||
const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections"))
|
||||
const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d"))
|
||||
end
|
||||
|
||||
if is_linux()
|
||||
@eval begin
|
||||
# avoid Conda update that causes Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234
|
||||
import Conda
|
||||
kw = Conda._installed_packages_dict()
|
||||
if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5"))
|
||||
print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n")
|
||||
print(add_backend_string(PyPlotBackend()))
|
||||
end
|
||||
end
|
||||
end
|
||||
# we don't want every command to update the figure
|
||||
PyPlot.ioff()
|
||||
end
|
||||
@@ -673,11 +683,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
z = transpose_z(series, z)
|
||||
if st == :surface
|
||||
clims = sp[:clims]
|
||||
if is_2tuple(clims)
|
||||
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
|
||||
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
|
||||
end
|
||||
if series[:fill_z] != nothing
|
||||
# the surface colors are different than z-value
|
||||
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
|
||||
@@ -1054,7 +1059,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
end
|
||||
if sp[:grid]
|
||||
fgcolor = py_color(sp[:foreground_color_grid])
|
||||
pyaxis[:grid](true, color = fgcolor, linestyle = ":")
|
||||
pyaxis[:grid](true, color = fgcolor)
|
||||
ax[:set_axisbelow](true)
|
||||
end
|
||||
py_set_axis_colors(ax, axis)
|
||||
@@ -1070,7 +1075,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
||||
py_add_legend(plt, sp, ax)
|
||||
|
||||
# this sets the bg color inside the grid
|
||||
ax[:set_facecolor](py_color(sp[:background_color_inside]))
|
||||
ax[:set_axis_bgcolor](py_color(sp[:background_color_inside]))
|
||||
end
|
||||
py_drawfig(fig)
|
||||
end
|
||||
@@ -1102,7 +1107,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]())
|
||||
sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||
sp.attr[:cbar_width] = _cbar_width + width(bb) + 1mm + (sp[:colorbar_title] == "" ? 0px : 30px)
|
||||
rightpad = rightpad + sp.attr[:cbar_width]
|
||||
end
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ function open_browser_window(filename::AbstractString)
|
||||
@static if is_apple()
|
||||
return run(`open $(filename)`)
|
||||
end
|
||||
@static if is_linux() || is_bsd() # is_bsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681
|
||||
@static if is_linux()
|
||||
return run(`xdg-open $(filename)`)
|
||||
end
|
||||
@static if is_windows()
|
||||
|
||||
+3
-3
@@ -174,7 +174,7 @@ function center(shape::Shape)
|
||||
Cx / 6A, Cy / 6A
|
||||
end
|
||||
|
||||
function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||
function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||
sx, sy = coords(shape)
|
||||
cx, cy = c
|
||||
for i=1:length(sx)
|
||||
@@ -184,7 +184,7 @@ function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||
shape
|
||||
end
|
||||
|
||||
function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||
function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
|
||||
shapecopy = deepcopy(shape)
|
||||
scale!(shapecopy, x, y, c)
|
||||
end
|
||||
@@ -521,7 +521,7 @@ Base.Array(surf::Surface) = surf.surf
|
||||
for f in (:length, :size)
|
||||
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
||||
end
|
||||
Base.copy(surf::Surface) = Surface(copy(surf.surf))
|
||||
Base.copy(surf::Surface) = Surface{typeof(surf.surf)}(copy(surf.surf))
|
||||
Base.eltype{T}(surf::Surface{T}) = eltype(T)
|
||||
|
||||
function expand_extrema!(a::Axis, surf::Surface)
|
||||
|
||||
@@ -172,24 +172,6 @@ PlotExample("",
|
||||
end)]
|
||||
),
|
||||
|
||||
PlotExample("Animation with subplots",
|
||||
"The `layout` macro can be used to create an animation with subplots.",
|
||||
[:(begin
|
||||
l = @layout([[a; b] c])
|
||||
p = plot(plot([sin,cos],1,leg=false),
|
||||
scatter([atan,cos],1,leg=false),
|
||||
plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l)
|
||||
|
||||
anim = Animation()
|
||||
for x = linspace(1,10π,100)
|
||||
plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)]))
|
||||
frame(anim)
|
||||
end
|
||||
end)]
|
||||
),
|
||||
|
||||
|
||||
|
||||
PlotExample("Open/High/Low/Close",
|
||||
"Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.",
|
||||
[:(begin
|
||||
|
||||
+1
-1
@@ -318,7 +318,7 @@ function setup_atom()
|
||||
# special handling for plotly... use PlotsDisplay
|
||||
function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend})
|
||||
display(Plots.PlotsDisplay(), plt)
|
||||
s = "PlotPane turned off. The plotly backend cannot render in the PlotPane due to javascript issues. Plotlyjs is similar to plotly and is compatible with the plot pane."
|
||||
s = "PlotPane turned off. The plotly and plotlyjs backends cannot render in the PlotPane due to javascript issues."
|
||||
Media.render(pane, Atom.div(Atom.HTML(s)))
|
||||
end
|
||||
end
|
||||
|
||||
+1
-8
@@ -277,13 +277,6 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW})
|
||||
attr[Symbol(letter,k)] = v
|
||||
end
|
||||
end
|
||||
for k in (:scale,), letter in (:x,:y,:z)
|
||||
# Series recipes may need access to this information
|
||||
lk = Symbol(letter,k)
|
||||
if haskey(attr, lk)
|
||||
kw[lk] = attr[lk]
|
||||
end
|
||||
end
|
||||
end
|
||||
sp_attrs[sp] = attr
|
||||
end
|
||||
@@ -364,7 +357,7 @@ function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
|
||||
expand_extrema!(sp[:xaxis], (0,w))
|
||||
expand_extrema!(sp[:yaxis], (0,h))
|
||||
sp[:yaxis].d[:flip] = true
|
||||
elseif !(st in (:pie, :histogram, :bins2d, :histogram2d))
|
||||
elseif !(st in (:pie, :histogram, :histogram2d))
|
||||
expand_extrema!(sp, d)
|
||||
end
|
||||
end
|
||||
|
||||
+52
-207
@@ -323,11 +323,10 @@ end
|
||||
|
||||
# create a bar plot as a filled step function
|
||||
@recipe function f(::Type{Val{:bar}}, x, y, z)
|
||||
procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y)
|
||||
nx, ny = length(procx), length(procy)
|
||||
nx, ny = length(x), length(y)
|
||||
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
|
||||
cv = [discrete_value!(axis, xi)[1] for xi=procx]
|
||||
procx = if nx == ny
|
||||
cv = [discrete_value!(axis, xi)[1] for xi=x]
|
||||
x = if nx == ny
|
||||
cv
|
||||
elseif nx == ny + 1
|
||||
0.5diff(cv) + cv[1:end-1]
|
||||
@@ -338,9 +337,9 @@ end
|
||||
# compute half-width of bars
|
||||
bw = d[:bar_width]
|
||||
hw = if bw == nothing
|
||||
0.5mean(diff(procx))
|
||||
0.5mean(diff(x))
|
||||
else
|
||||
Float64[0.5cycle(bw,i) for i=1:length(procx)]
|
||||
Float64[0.5cycle(bw,i) for i=1:length(x)]
|
||||
end
|
||||
|
||||
# make fillto a vector... default fills to 0
|
||||
@@ -348,21 +347,16 @@ end
|
||||
if fillto == nothing
|
||||
fillto = 0
|
||||
end
|
||||
if (yscale in _logScales) && !all(_is_positive, fillto)
|
||||
fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto)
|
||||
end
|
||||
|
||||
# create the bar shapes by adding x/y segments
|
||||
xseg, yseg = Segments(), Segments()
|
||||
for i=1:ny
|
||||
yi = procy[i]
|
||||
if !isnan(yi)
|
||||
center = procx[i]
|
||||
hwi = cycle(hw,i)
|
||||
fi = cycle(fillto,i)
|
||||
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
|
||||
push!(yseg, yi, fi, fi, yi, yi)
|
||||
end
|
||||
center = x[i]
|
||||
hwi = cycle(hw,i)
|
||||
yi = y[i]
|
||||
fi = cycle(fillto,i)
|
||||
push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi)
|
||||
push!(yseg, yi, fi, fi, yi, yi)
|
||||
end
|
||||
|
||||
# widen limits out a bit
|
||||
@@ -380,7 +374,6 @@ end
|
||||
x := xseg.pts
|
||||
y := yseg.pts
|
||||
seriestype := :shape
|
||||
ylims --> wautolims
|
||||
()
|
||||
end
|
||||
@deps bar shape
|
||||
@@ -391,76 +384,9 @@ end
|
||||
|
||||
_bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2
|
||||
|
||||
_is_positive(x) = (x > 0) && !(x ≈ 0)
|
||||
|
||||
_positive_else_nan{T}(::Type{T}, x::Real) = _is_positive(x) ? T(x) : T(NaN)
|
||||
|
||||
function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, scale::Symbol)
|
||||
if scale in _logScales
|
||||
[_positive_else_nan(T, x) for x in V]
|
||||
else
|
||||
[T(x) for x in V]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
|
||||
if (scale in _logScales)
|
||||
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
|
||||
else
|
||||
zero(T)
|
||||
end
|
||||
end
|
||||
|
||||
function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol)
|
||||
lo = if (scale in _logScales)
|
||||
_binbarlike_baseline(min_value, scale)
|
||||
else
|
||||
min(min_value * T(1.1), zero(T))
|
||||
end::T
|
||||
|
||||
hi = if !isnan(max_value)
|
||||
if (scale in _logScales)
|
||||
max_value * T(_logScaleBases[scale]^log10(2))
|
||||
else
|
||||
max(max_value * T(1.1), zero(T))
|
||||
end
|
||||
else
|
||||
one(T)
|
||||
end::T
|
||||
|
||||
(lo, hi)
|
||||
end
|
||||
|
||||
|
||||
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
|
||||
w_adj = _scale_adjusted_values(T, w, wscale)
|
||||
w_min = minimum(w_adj)
|
||||
w_max = maximum(w_adj)
|
||||
baseline = _binbarlike_baseline(w_min, wscale)
|
||||
autolims = _binbarlike_autolims(w_min, w_max,wscale)
|
||||
w_adj, baseline, autolims
|
||||
end
|
||||
|
||||
function _preprocess_barlike(d, x, y)
|
||||
xscale = get(d, :xscale, :identity)
|
||||
yscale = get(d, :yscale, :identity)
|
||||
weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
|
||||
x, weights, xscale, yscale, baseline, wautolims
|
||||
end
|
||||
|
||||
function _preprocess_binlike(d, x, y)
|
||||
xscale = get(d, :xscale, :identity)
|
||||
yscale = get(d, :yscale, :identity)
|
||||
T = float(promote_type(eltype(x), eltype(y)))
|
||||
edge = T.(x)
|
||||
weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale)
|
||||
edge, weights, xscale, yscale, baseline, wautolims
|
||||
end
|
||||
|
||||
|
||||
@recipe function f(::Type{Val{:barbins}}, x, y, z)
|
||||
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||
edge, weights = x, y
|
||||
if (d[:bar_width] == nothing)
|
||||
bar_width := diff(edge)
|
||||
end
|
||||
@@ -469,11 +395,11 @@ end
|
||||
seriestype := :bar
|
||||
()
|
||||
end
|
||||
@deps barbins bar
|
||||
@deps barbins bins
|
||||
|
||||
|
||||
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
||||
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||
edge, weights = x, y
|
||||
xerror := diff(edge)/2
|
||||
x := _bin_centers(edge)
|
||||
y := weights
|
||||
@@ -483,65 +409,43 @@ end
|
||||
@deps scatterbins scatter
|
||||
|
||||
|
||||
function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol)
|
||||
log_scale_x = xscale in _logScales
|
||||
log_scale_y = yscale in _logScales
|
||||
|
||||
function _stepbins_path(edge, weights)
|
||||
nbins = length(linearindices(weights))
|
||||
if length(linearindices(edge)) != nbins + 1
|
||||
error("Edge vector must be 1 longer than weight vector")
|
||||
end
|
||||
|
||||
x = eltype(edge)[]
|
||||
y = eltype(weights)[]
|
||||
|
||||
it_e, it_w = start(edge), start(weights)
|
||||
a, it_e = next(edge, it_e)
|
||||
last_w = eltype(weights)(NaN)
|
||||
i = 1
|
||||
while (!done(edge, it_e) && !done(edge, it_e))
|
||||
b, it_e = next(edge, it_e)
|
||||
w, it_w = next(weights, it_w)
|
||||
px, it_e = next(edge, it_e)
|
||||
py = zero(eltype(weights))
|
||||
|
||||
if (log_scale_x && a ≈ 0)
|
||||
a = b/_logScaleBases[xscale]^3
|
||||
end
|
||||
npathpts = 2 * nbins + 2
|
||||
x = Vector{eltype(px)}(npathpts)
|
||||
y = Vector{eltype(py)}(npathpts)
|
||||
|
||||
if isnan(w)
|
||||
if !isnan(last_w)
|
||||
push!(x, a)
|
||||
push!(y, baseline)
|
||||
end
|
||||
else
|
||||
if isnan(last_w)
|
||||
push!(x, a)
|
||||
push!(y, baseline)
|
||||
end
|
||||
push!(x, a)
|
||||
push!(y, w)
|
||||
push!(x, b)
|
||||
push!(y, w)
|
||||
end
|
||||
|
||||
a = b
|
||||
last_w = w
|
||||
end
|
||||
if (last_w != baseline)
|
||||
push!(x, a)
|
||||
push!(y, baseline)
|
||||
x[1], y[1] = px, py
|
||||
i = 2
|
||||
while (i < npathpts - 1)
|
||||
py, it_w = next(weights, it_w)
|
||||
x[i], y[i] = px, py
|
||||
i += 1
|
||||
px, it_e = next(edge, it_e)
|
||||
x[i], y[i] = px, py
|
||||
i += 1
|
||||
end
|
||||
assert(i == npathpts)
|
||||
x[end], y[end] = px, zero(py)
|
||||
|
||||
(x, y)
|
||||
end
|
||||
|
||||
|
||||
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
|
||||
edge, weights = x, y
|
||||
|
||||
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
|
||||
|
||||
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||
|
||||
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
|
||||
if !isvertical(d)
|
||||
xpts, ypts = _stepbins_path(edge, weights)
|
||||
if !Plots.isvertical(d)
|
||||
xpts, ypts = ypts, xpts
|
||||
end
|
||||
|
||||
@@ -549,7 +453,7 @@ end
|
||||
if d[:markershape] != :none
|
||||
@series begin
|
||||
seriestype := :scatter
|
||||
x := _bin_centers(edge)
|
||||
x := Plots._bin_centers(edge)
|
||||
y := weights
|
||||
fillrange := nothing
|
||||
label := ""
|
||||
@@ -564,8 +468,7 @@ end
|
||||
x := xpts
|
||||
y := ypts
|
||||
seriestype := :path
|
||||
|
||||
ylims --> wautolims
|
||||
ylims --> [0, 1.1 * maximum(weights)]
|
||||
()
|
||||
end
|
||||
Plots.@deps stepbins path
|
||||
@@ -582,11 +485,9 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode
|
||||
|
||||
v = vs[dim]
|
||||
|
||||
if mode == :auto
|
||||
30
|
||||
elseif mode == :sqrt # Square-root choice
|
||||
if mode == :sqrt # Square-root choice
|
||||
_cl(sqrt(n))
|
||||
elseif mode == :sturges # Sturges' formula
|
||||
elseif mode == :sturges || mode ==:auto # Sturges' formula
|
||||
_cl(log2(n)) + 1
|
||||
elseif mode == :rice # Rice Rule
|
||||
_cl(2 * n^(1/3))
|
||||
@@ -596,7 +497,7 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode
|
||||
_cl(_span(v) / (2 * _iqr(v) / n^(1/3)))
|
||||
else
|
||||
error("Unknown auto-binning mode $mode")
|
||||
end::Int
|
||||
end
|
||||
end
|
||||
|
||||
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left)
|
||||
@@ -610,14 +511,13 @@ _hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, Abs
|
||||
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
|
||||
|
||||
_hist_norm_mode(mode::Symbol) = mode
|
||||
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
|
||||
_hist_norm_mode(mode::Bool) = mode ? :norm : :none
|
||||
|
||||
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
|
||||
info("binning = $binning")
|
||||
edges = _hist_edges(vs, binning)
|
||||
h = float( weights == nothing ?
|
||||
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
|
||||
StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left)
|
||||
StatsBase.fit(StatsBase.Histogram, vs, edges) :
|
||||
StatsBase.fit(StatsBase.Histogram, vs, weights, edges)
|
||||
)
|
||||
normalize!(h, mode = _hist_norm_mode(normed))
|
||||
end
|
||||
@@ -668,10 +568,9 @@ end
|
||||
|
||||
if d[:seriestype] == :scatterbins
|
||||
# Workaround, error bars currently not set correctly by scatterbins
|
||||
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights)
|
||||
xerror --> diff(h.edges[1])/2
|
||||
seriestype := :scatter
|
||||
(Plots._bin_centers(edge), weights)
|
||||
(Plots._bin_centers(h.edges[1]), h.weights)
|
||||
else
|
||||
(h.edges[1], h.weights)
|
||||
end
|
||||
@@ -1040,70 +939,16 @@ abline!(args...; kw...) = abline!(current(), args...; kw...)
|
||||
# -------------------------------------------------
|
||||
# Dates
|
||||
|
||||
dateformatter(dt) = string(convert(Date, dt))
|
||||
datetimeformatter(dt) = string(convert(DateTime, dt))
|
||||
|
||||
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, dt), dateformatter)
|
||||
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int, dt), datetimeformatter)
|
||||
@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int,dt), dt -> string(convert(Date,dt)))
|
||||
@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), dt -> string(convert(DateTime,dt)))
|
||||
|
||||
# -------------------------------------------------
|
||||
# Complex Numbers
|
||||
|
||||
@recipe function f{T<:Number}(A::Array{Complex{T}})
|
||||
xguide --> "Re(x)"
|
||||
yguide --> "Im(x)"
|
||||
real.(A), imag.(A)
|
||||
end
|
||||
|
||||
# Splits a complex matrix to its real and complex parts
|
||||
# Reals defaults solid, imaginary defaults dashed
|
||||
# Label defaults are changed to match the real-imaginary reference / indexing
|
||||
@recipe function f{T<:Real,T2}(x::AbstractArray{T},y::Array{Complex{T2}})
|
||||
ylabel --> "Re(y)"
|
||||
zlabel --> "Im(y)"
|
||||
x,real.(y),imag.(y)
|
||||
end
|
||||
|
||||
|
||||
# --------------------------------------------------
|
||||
# Color Gradients
|
||||
|
||||
@userplot ShowLibrary
|
||||
@recipe function f(cl::ShowLibrary)
|
||||
if !(length(cl.args) == 1 && isa(cl.args[1], Symbol))
|
||||
error("showlibrary takes the name of a color library as a Symbol")
|
||||
end
|
||||
|
||||
library = PlotUtils.color_libraries[cl.args[1]]
|
||||
z = sqrt.((1:15)*(1:20)')
|
||||
|
||||
seriestype := :heatmap
|
||||
ticks := nothing
|
||||
legend := false
|
||||
|
||||
layout --> length(library.lib)
|
||||
|
||||
i = 0
|
||||
for grad in sort(collect(keys(library.lib)))
|
||||
@series begin
|
||||
seriescolor := cgrad(grad, cl.args[1])
|
||||
title := string(grad)
|
||||
subplot := i += 1
|
||||
z
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@userplot ShowGradient
|
||||
@recipe function f(grad::ShowGradient)
|
||||
if !(length(grad.args) == 1 && isa(grad.args[1], Symbol))
|
||||
error("showgradient takes the name of a color gradient as a Symbol")
|
||||
end
|
||||
z = sqrt.((1:15)*(1:20)')
|
||||
seriestype := :heatmap
|
||||
ticks := nothing
|
||||
legend := false
|
||||
seriescolor := grad.args[1]
|
||||
title := string(grad.args[1])
|
||||
z
|
||||
@userplot ComplexPlot
|
||||
@recipe function f(cp::ComplexPlot)
|
||||
xguide --> "Real Part"
|
||||
yguide --> "Imaginary Part"
|
||||
seriestype --> :scatter
|
||||
real(cp.args[1]), imag(cp.args[1])
|
||||
end
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot]
|
||||
function should_add_to_legend(series::Series)
|
||||
series.d[:primary] && series.d[:label] != "" &&
|
||||
!(series.d[:seriestype] in (
|
||||
:hexbin,:bins2d,:histogram2d,:hline,:vline,
|
||||
:hexbin,:histogram2d,:hline,:vline,
|
||||
:contour,:contourf,:contour3d,:surface,:wireframe,
|
||||
:heatmap, :pie, :image
|
||||
))
|
||||
|
||||
+2
-4
@@ -2,8 +2,7 @@
|
||||
function theme(s::Symbol; kw...)
|
||||
# reset?
|
||||
if s == :none || s == :default
|
||||
PlotUtils.clibrary(:Plots)
|
||||
PlotUtils.default_cgrad(default = :sequential, sequential = :inferno)
|
||||
PlotUtils._default_gradient[] = :inferno
|
||||
default(;
|
||||
bg = :white,
|
||||
bglegend = :match,
|
||||
@@ -24,8 +23,7 @@ function theme(s::Symbol; kw...)
|
||||
# update the default gradient and other defaults
|
||||
thm = PlotThemes._themes[s]
|
||||
if thm.gradient != nothing
|
||||
PlotUtils.clibrary(:misc)
|
||||
PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s))
|
||||
PlotUtils._default_gradient[] = PlotThemes.gradient_name(s)
|
||||
end
|
||||
default(;
|
||||
bg = thm.bg_secondary,
|
||||
|
||||
Reference in New Issue
Block a user