From 3a7887d00347f848639bb28c791049d34d022dd9 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Mon, 28 Sep 2015 14:58:56 -0400 Subject: [PATCH] working on massive naming overhaul and fixes --- README.md | 24 +++++++-------- docs/example_generation.jl | 12 ++++---- docs/gadfly_examples.md | 2 +- docs/immerse_examples.md | 2 +- docs/pyplot_examples.md | 2 +- docs/qwt_examples.md | 2 +- docs/readme_template.md | 26 ++++++++-------- docs/unicodeplots_examples.md | 2 +- docs/winston_examples.md | 2 +- examples/annotate.ipynb | 4 +-- examples/iris.ipynb | 8 ++--- examples/playground.ipynb | 8 ++--- examples/plotupdates.ipynb | 6 ++-- examples/ticks_and_limits.ipynb | 54 +++++++++++++++++++++++++++++++-- src/Plots.jl | 22 ++++++-------- src/args.jl | 33 +++++++++++++------- src/backends/gadfly.jl | 53 ++++++++++++++++++++++++++++---- src/backends/immerse.jl | 8 ++--- src/backends/pyplot.jl | 4 +-- src/backends/qwt.jl | 4 +-- src/backends/template.jl | 4 +-- src/backends/unicodeplots.jl | 4 +-- src/backends/winston.jl | 4 +-- src/colors.jl | 2 +- src/plot.jl | 38 +++++++++++------------ src/plotter.jl | 12 ++++---- src/subplot.jl | 41 +++++++++++++------------ src/types.jl | 4 +-- test/runtests.jl | 26 ++++++++-------- 29 files changed, 256 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 495f1a39..249a988e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Pkg.add("Winston") ## Use -Load it in. The underlying plotting backends are not imported until `plotter()` is called (which happens +Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens on your first call to `plot` or `subplot`). This means that you don't need any backends to be installed when you call `using Plots`. Plots will try to figure out a good default backend for you automatically based on what backends are installed. @@ -54,7 +54,7 @@ using Plots Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png: ```julia -gadfly!() # switch to Gadfly as a backend +gadfly() # switch to Gadfly as a backend dataframes!() # turn on support for DataFrames inputs # load some data @@ -72,21 +72,21 @@ Also check out the [IJulia notebooks](examples) and see how it works interactive ## API -Call `plotter!(backend::Symbol)` or the shorthands (`gadfly!()`, `qwt!()`, `unicodeplots!()`, etc) to set the current plotting backend. +Call `backend(backend::Symbol)` or the shorthands (`gadfly()`, `qwt()`, `unicodeplots()`, etc) to set the current plotting backend. Subsequent commands are converted into the relevant plotting commands for that package: ```julia -gadfly!() +gadfly() plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)` -qwt!() +qwt() plot(1:10) # this effectively calls `Qwt.plot(1:10)` ``` Use `plot` to create a new plot object, and `plot!` to add to an existing one: ```julia -plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot` -plot!(args...; kw...) # adds to the `currentPlot` +plot(args...; kw...) # creates a new plot window, and sets it to be the `current` +plot!(args...; kw...) # adds to the `current` plot!(plotobj, args...; kw...) # adds to the plot `plotobj` ``` @@ -104,7 +104,7 @@ In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to the relevant column(s). -Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `currentPlot()`. +Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`. ```julia plot() # empty plot object @@ -162,9 +162,9 @@ vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline) ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc) ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc) -title!(s::AbstractString) = plot!(title = s) -xlabel!(s::AbstractString) = plot!(xlabel = s) -ylabel!(s::AbstractString) = plot!(ylabel = s) +title(s::AbstractString) = plot!(title = s) +xlabel(s::AbstractString) = plot!(xlabel = s) +ylabel(s::AbstractString) = plot!(ylabel = s) xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims) ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims) xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v) @@ -262,7 +262,7 @@ Type | Aliases -__Tip__: You can see the default value for a given argument with `plotDefault(arg::Symbol)`, and set the default value with `plotDefault!(arg::Symbol, value)` +__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` __Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in an array to cycle through values. Example: diff --git a/docs/example_generation.jl b/docs/example_generation.jl index 1a83a916..b8916f0e 100644 --- a/docs/example_generation.jl +++ b/docs/example_generation.jl @@ -105,9 +105,9 @@ createStringOfMarkDownSymbols(arr) = isempty(arr) ? "" : createStringOfMarkDownC function generate_markdown(pkgname::Symbol) - # set up the plotter, and don't show the plots by default - pkg = plotter!(pkgname) - # plotDefault!(:show, false) + # set up the backend, and don't show the plots by default + pkg = backend(pkgname) + # default(:show, false) # mkdir if necessary try @@ -166,10 +166,10 @@ end # make and display one plot function test_example(pkgname::Symbol, idx::Int) println("Testing plot: $pkgname:$idx:$(examples[idx].header)") - plotter!(pkgname) - plotter() + backend(pkgname) + backend() map(eval, examples[idx].exprs) - plt = currentPlot() + plt = current() gui(plt) plt end diff --git a/docs/gadfly_examples.md b/docs/gadfly_examples.md index 079571e5..8cd3657c 100644 --- a/docs/gadfly_examples.md +++ b/docs/gadfly_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -gadfly!() +gadfly() ``` ### Lines diff --git a/docs/immerse_examples.md b/docs/immerse_examples.md index a66ee7bb..5b380b15 100644 --- a/docs/immerse_examples.md +++ b/docs/immerse_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -immerse!() +immerse() ``` ### Lines diff --git a/docs/pyplot_examples.md b/docs/pyplot_examples.md index 39ddee0f..c7363fee 100644 --- a/docs/pyplot_examples.md +++ b/docs/pyplot_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -pyplot!() +pyplot() ``` ### Lines diff --git a/docs/qwt_examples.md b/docs/qwt_examples.md index 74c3d75b..3a820a9b 100644 --- a/docs/qwt_examples.md +++ b/docs/qwt_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -qwt!() +qwt() ``` ### Lines diff --git a/docs/readme_template.md b/docs/readme_template.md index 012bc3d3..77aa59f8 100644 --- a/docs/readme_template.md +++ b/docs/readme_template.md @@ -43,7 +43,7 @@ Pkg.add("Winston") ## Use -Load it in. The underlying plotting backends are not imported until `plotter()` is called (which happens +Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens on your first call to `plot` or `subplot`). This means that you don't need any backends to be installed when you call `using Plots`. Plots will try to figure out a good default backend for you automatically based on what backends are installed. @@ -54,8 +54,8 @@ using Plots Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png: ```julia -gadfly!() # switch to Gadfly as a backend -dataframes!() # turn on support for DataFrames inputs +gadfly() # switch to Gadfly as a backend +dataframes() # turn on support for DataFrames inputs # load some data using RDatasets @@ -72,21 +72,21 @@ Also check out the [IJulia notebooks](examples) and see how it works interactive ## API -Call `plotter!(backend::Symbol)` or the shorthands (`gadfly!()`, `qwt!()`, `unicodeplots!()`, etc) to set the current plotting backend. +Call `backend(backend::Symbol)` or the shorthands (`gadfly()`, `qwt()`, `unicodeplots()`, etc) to set the current plotting backend. Subsequent commands are converted into the relevant plotting commands for that package: ```julia -gadfly!() +gadfly() plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)` -qwt!() +qwt() plot(1:10) # this effectively calls `Qwt.plot(1:10)` ``` Use `plot` to create a new plot object, and `plot!` to add to an existing one: ```julia -plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot` -plot!(args...; kw...) # adds to the `currentPlot` +plot(args...; kw...) # creates a new plot window, and sets it to be the `current` +plot!(args...; kw...) # adds to the `current` plot!(plotobj, args...; kw...) # adds to the plot `plotobj` ``` @@ -98,13 +98,13 @@ There are many ways to pass in data to the plot functions... some examples: - Vectors of Vectors - Functions - Vectors of Functions -- DataFrames with column symbols (initialize with `dataframes!()`) +- DataFrames with column symbols (initialize with `dataframes()`) In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type(s) you want, and Plots will slice up the data as needed. For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to the relevant column(s). -Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `currentPlot()`. +Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`. ```julia plot() # empty plot object @@ -118,7 +118,7 @@ plot(rand(10), sin) # same... y = sin(x) plot([sin,cos], 0:0.1:π) # plot 2 series, sin(x) and cos(x) plot([sin,cos], 0, π) # plot sin and cos on the range [0, π] plot(1:10, Any[rand(10), sin]) # plot 2 series, y = rand(10) for the first, y = sin(x) for the second... x = 1:10 for both -plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes!()` first to import DataFrames and initialize) +plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes()` first to import DataFrames and initialize) ``` You can update certain plot settings after plot creation (not supported on all backends): @@ -169,7 +169,7 @@ xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims) ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims) xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v) yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v) -annotate!(annotations) = plot!(annotation = annotations) +annotate!(anns) = plot!(annotation = anns) ``` Some keyword arguments you can set: @@ -189,7 +189,7 @@ Markers: [[MARKERS_TABLE]] -__Tip__: You can see the default value for a given argument with `plotDefault(arg::Symbol)`, and set the default value with `plotDefault!(arg::Symbol, value)` +__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` __Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in an array to cycle through values. Example: diff --git a/docs/unicodeplots_examples.md b/docs/unicodeplots_examples.md index ad3f526e..1a95f252 100644 --- a/docs/unicodeplots_examples.md +++ b/docs/unicodeplots_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -unicodeplots!() +unicodeplots() ``` ### Lines diff --git a/docs/winston_examples.md b/docs/winston_examples.md index 85079ec8..686d5180 100644 --- a/docs/winston_examples.md +++ b/docs/winston_examples.md @@ -11,7 +11,7 @@ ```julia using Plots -winston!() +winston() ``` ### Lines diff --git a/examples/annotate.ipynb b/examples/annotate.ipynb index 30808c26..17f6b875 100644 --- a/examples/annotate.ipynb +++ b/examples/annotate.ipynb @@ -35,8 +35,8 @@ } ], "source": [ - "using Plots; winston!()\n", - "plotDefault!(size=(600,400),leg=false)\n", + "using Plots; winston()\n", + "default(size=(600,400),leg=false)\n", "y = rand(10)\n", "plot(y, ann=[(3,y[3],\"this is #3\"), (8,y[8],\"this is #8\")])" ] diff --git a/examples/iris.ipynb b/examples/iris.ipynb index c88f6a6b..7448196e 100644 --- a/examples/iris.ipynb +++ b/examples/iris.ipynb @@ -35,9 +35,9 @@ } ], "source": [ - "using RDatasets, Plots; dataframes!()\n", + "using RDatasets, Plots; dataframes()\n", "iris = dataset(\"datasets\", \"iris\");\n", - "plotDefault!(size=(600,400));" + "default(size=(600,400));" ] }, { @@ -49,7 +49,7 @@ }, "outputs": [], "source": [ - "gadfly!();\n", + "gadfly();\n", "scatter(iris, :SepalLength, :SepalWidth, group=:Species, ms=12, m=[:+,:h,:s])" ] }, @@ -65,7 +65,7 @@ "\n", "plot!(u->6+2*sin(u), u->3+cos(u), 0, 2π, lab=\"an oval\", fill=3)\n", "plot!(Any[[6],[3]], t=[:vline,:hline], w=4, c=RGB(1,0,0))\n", - "title!(\"Playing around with series\")" + "title(\"Playing around with series\")" ] }, { diff --git a/examples/playground.ipynb b/examples/playground.ipynb index 9ba4c648..90664b35 100644 --- a/examples/playground.ipynb +++ b/examples/playground.ipynb @@ -34,7 +34,7 @@ } ], "source": [ - "using Plots; gadfly!(); plotDefault!(size=(400,300),leg=false)\n", + "using Plots; gadfly(); default(size=(400,300),leg=false)\n", "n = 10\n", "#cs = distinguishable_colors(n)\n", "cs = [colorant\"red\",colorant\"blue\",colorant\"yellow\",colorant\"blue\"]\n", @@ -89,8 +89,8 @@ } ], "source": [ - "using Plots; qwt!()\n", - "plotDefault!(:size, (500,300));" + "using Plots; qwt()\n", + "default(:size, (500,300));" ] }, { @@ -268,7 +268,7 @@ } ], "source": [ - "using Plots; gadfly!()\n", + "using Plots; gadfly()\n", "plot(cumsum(randn(100,5),1), w=8, style=:auto)\n", "plot!(rand(1,10)*10, style=:auto, t=[:hline,:vline])" ] diff --git a/examples/plotupdates.ipynb b/examples/plotupdates.ipynb index 8cd5b91c..048e5239 100644 --- a/examples/plotupdates.ipynb +++ b/examples/plotupdates.ipynb @@ -8,7 +8,7 @@ }, "outputs": [], "source": [ - "using Plots; pyplot!()" + "using Plots; pyplot()" ] }, { @@ -39,8 +39,8 @@ } ], "source": [ - "using Plots; immerse!()\n", - "plotDefault!(:size, (500,300));" + "using Plots; immerse()\n", + "default(:size, (500,300));" ] }, { diff --git a/examples/ticks_and_limits.ipynb b/examples/ticks_and_limits.ipynb index bbfd115a..e053f39a 100644 --- a/examples/ticks_and_limits.ipynb +++ b/examples/ticks_and_limits.ipynb @@ -1,5 +1,55 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Plots.jl] Switched to backend: gadfly" + ] + }, + { + "ename": "MethodError", + "evalue": "MethodError: `isless` has no method matching isless(::ASCIIString, ::Int64)\nClosest candidates are:\n isless(!Matched::AbstractFloat, ::Real)\n isless(!Matched::Real, ::Real)\n isless(!Matched::Char, ::Integer)\n ...", + "output_type": "error", + "traceback": [ + "MethodError: `isless` has no method matching isless(::ASCIIString, ::Int64)\nClosest candidates are:\n isless(!Matched::AbstractFloat, ::Real)\n isless(!Matched::Real, ::Real)\n isless(!Matched::Char, ::Integer)\n ...", + "", + " in min at operators.jl:58", + " in apply_statistic at /home/tom/.julia/v0.4/Gadfly/src/statistics.jl:818", + " in apply_statistics at /home/tom/.julia/v0.4/Gadfly/src/statistics.jl:38", + " in render_prepare at /home/tom/.julia/v0.4/Gadfly/src/Gadfly.jl:676", + " in render at /home/tom/.julia/v0.4/Gadfly/src/Gadfly.jl:717", + " in draw at /home/tom/.julia/v0.4/Gadfly/src/Gadfly.jl:821", + " in writemime at /home/tom/.julia/v0.4/Plots/src/backends/gadfly.jl:352", + " in base64encode at base64.jl:160", + " in display_dict at /home/tom/.julia/v0.4/IJulia/src/execute_request.jl:32" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "ticks = Union{ASCIIString,UTF8String}[\"x01\",\"x02\",\"x03\",\"x04\",\"x05\",\"x06\",\"x07\",\"x08\",\"x09\",\"x10\"]\n" + ] + } + ], + "source": [ + "using Plots, StatsBase\n", + "gadfly()\n", + "xstr = [@sprintf(\"x%02d\",i) for i in 1:10]\n", + "x = sort(sample(xstr, 100))\n", + "y = rand(length(x))\n", + "scatter(x,y)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -7,9 +57,7 @@ "collapsed": true }, "outputs": [], - "source": [ - "using Plots; gadfly!()" - ] + "source": [] } ], "metadata": { diff --git a/src/Plots.jl b/src/Plots.jl index d3530630..e387035a 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -6,19 +6,16 @@ using Reexport @reexport using Colors export - plotter, - plotter!, plot, plot!, - plot_display, - plot_display!, + # plot_display, + # plot_display!, subplot, subplot!, - currentPlot, - currentPlot!, - plotDefault, - plotDefault!, + current, + default, + scatter, scatter!, bar, @@ -48,9 +45,10 @@ export savepng, gui, + backend, backends, aliases, - dataframes!, + dataframes, OHLC, supportedArgs, @@ -119,13 +117,13 @@ annotate!(plt::Plot, anns) = plot!(plt; annotation = # --------------------------------------------------------- -savepng(args...; kw...) = savepng(currentPlot(), args...; kw...) +savepng(args...; kw...) = savepng(current(), args...; kw...) savepng(plt::PlottingObject, fn::AbstractString; kw...) = (io = open(fn, "w"); writemime(io, MIME("image/png"), plt); close(io)) -# savepng(plt::PlottingObject, args...; kw...) = savepng(plt.plotter, plt, args...; kw...) +# savepng(plt::PlottingObject, args...; kw...) = savepng(plt.backend, plt, args...; kw...) # savepng(::PlottingPackage, plt::PlottingObject, fn::AbstractString, args...) = error("unsupported") # fallback so multiple dispatch doesn't get confused if it's missing -gui(plt::PlottingObject = currentPlot()) = display(PlotsDisplay(), plt) +gui(plt::PlottingObject = current()) = display(PlotsDisplay(), plt) # override the REPL display to open a gui window diff --git a/src/args.jl b/src/args.jl index 4c4405c5..9bb7890b 100644 --- a/src/args.jl +++ b/src/args.jl @@ -79,11 +79,11 @@ supportedStyles(::PlottingPackage) = _allStyles supportedMarkers(::PlottingPackage) = _allMarkers subplotSupported(::PlottingPackage) = true -supportedAxes() = supportedAxes(plotter()) -supportedTypes() = supportedTypes(plotter()) -supportedStyles() = supportedStyles(plotter()) -supportedMarkers() = supportedMarkers(plotter()) -subplotSupported() = subplotSupported(plotter()) +supportedAxes() = supportedAxes(backend()) +supportedTypes() = supportedTypes(backend()) +supportedStyles() = supportedStyles(backend()) +supportedMarkers() = supportedMarkers(backend()) +subplotSupported() = subplotSupported(backend()) # ----------------------------------------------------------------------------- @@ -126,8 +126,13 @@ _plotDefaults[:ylims] = :auto _plotDefaults[:xticks] = :auto _plotDefaults[:yticks] = :auto _plotDefaults[:size] = (800,600) +_plotDefaults[:pos] = (0,0) _plotDefaults[:windowtitle] = "Plots.jl" _plotDefaults[:show] = false +_plotDefaults[:layout] = nothing +_plotDefaults[:n] = -1 +_plotDefaults[:nr] = -1 +_plotDefaults[:nc] = -1 @@ -135,7 +140,7 @@ _plotDefaults[:show] = false const _allArgs = sort(collect(union(keys(_seriesDefaults), keys(_plotDefaults)))) supportedArgs(::PlottingPackage) = _allArgs -supportedArgs() = supportedArgs(plotter()) +supportedArgs() = supportedArgs(backend()) # ----------------------------------------------------------------------------- @@ -235,7 +240,13 @@ end # update the defaults globally -function plotDefault(k::Symbol) +""" +`default(key)` returns the current default value for that key +`default(key, value)` sets the current default value for that key +`default(; kw...)` will set the current default value for each key/value pair +""" + +function default(k::Symbol) k = get(_keyAliases, k, k) if haskey(_seriesDefaults, k) return _seriesDefaults[k] @@ -246,7 +257,7 @@ function plotDefault(k::Symbol) end end -function plotDefault!(k::Symbol, v) +function default(k::Symbol, v) k = get(_keyAliases, k, k) if haskey(_seriesDefaults, k) _seriesDefaults[k] = v @@ -257,9 +268,9 @@ function plotDefault!(k::Symbol, v) end end -function plotDefault!(; kw...) +function default(; kw...) for (k,v) in kw - plotDefault!(k, v) + default(k, v) end end @@ -297,7 +308,7 @@ end function warnOnUnsupportedArgs(pkg::PlottingPackage, d::Dict) for k in sortedkeys(d) - if !(k in supportedArgs(pkg)) + if !(k in supportedArgs(pkg)) && d[k] != default(k) warn("Keyword argument $k not supported with $pkg. Choose from: $(supportedArgs(pkg))") end end diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index fd9f78d9..4fa93d0e 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -3,11 +3,52 @@ immutable GadflyPackage <: PlottingPackage end -export gadfly! -gadfly!() = plotter!(:gadfly) +export gadfly +gadfly() = backend(:gadfly) -supportedArgs(::GadflyPackage) = setdiff(_allArgs, [:heatmap_c, :pos, :screen, :yrightlabel]) +# supportedArgs(::GadflyPackage) = setdiff(_allArgs, [:heatmap_c, :pos, :screen, :yrightlabel]) +supportedArgs(::GadflyPackage) = [ + :annotation, + :args, + :axis, + :background_color, + :color, + :fillto, + :foreground_color, + :group, + # :heatmap_c, + :kwargs, + :label, + :layout, + :legend, + :linestyle, + :linetype, + :marker, + :markercolor, + :markersize, + :n, + :nbins, + :nc, + :nr, + # :pos, + :reg, + # :ribbon, + :show, + :size, + :title, + :width, + :windowtitle, + :x, + :xlabel, + :xlims, + :xticks, + :y, + :ylabel, + :ylims, + # :yrightlabel, + :yticks, + ] supportedAxes(::GadflyPackage) = [:auto, :left] supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc] supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] @@ -336,7 +377,7 @@ function buildGadflySubplotContext(subplt::Subplot) i = 0 rows = [] for rowcnt in subplt.layout.rowcounts - push!(rows, Gadfly.hstack([getGadflyContext(plt.plotter, plt) for plt in subplt.plts[(1:rowcnt) + i]]...)) + push!(rows, Gadfly.hstack([getGadflyContext(plt.backend, plt) for plt in subplt.plts[(1:rowcnt) + i]]...)) i += rowcnt end Gadfly.vstack(rows...) @@ -347,7 +388,7 @@ function setGadflyDisplaySize(w,h) end function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{GadflyPackage}) - gplt = getGadflyContext(plt.plotter, plt) + gplt = getGadflyContext(plt.backend, plt) setGadflyDisplaySize(plt.initargs[:size]...) Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt) end @@ -361,7 +402,7 @@ end function Base.writemime(io::IO, ::MIME"image/png", plt::Subplot{GadflyPackage}) - gplt = getGadflyContext(plt.plotter, plt) + gplt = getGadflyContext(plt.backend, plt) setGadflyDisplaySize(plt.initargs[1][:size]...) Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt) end diff --git a/src/backends/immerse.jl b/src/backends/immerse.jl index d877c847..f8b11a50 100644 --- a/src/backends/immerse.jl +++ b/src/backends/immerse.jl @@ -3,8 +3,8 @@ immutable ImmersePackage <: PlottingPackage end -export immerse! -immerse!() = plotter!(:immerse) +export immerse +immerse() = backend(:immerse) supportedArgs(::ImmersePackage) = supportedArgs(GadflyPackage()) @@ -128,7 +128,7 @@ getGadflyContext(::ImmersePackage, plt::Plot) = plt.o[2] getGadflyContext(::ImmersePackage, subplt::Subplot) = buildGadflySubplotContext(subplt) function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{ImmersePackage}) - gplt = getGadflyContext(plt.plotter, plt) + gplt = getGadflyContext(plt.backend, plt) setGadflyDisplaySize(plt.initargs[:size]...) Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt) end @@ -148,7 +148,7 @@ end function Base.writemime(io::IO, ::MIME"image/png", plt::Subplot{ImmersePackage}) - gplt = getGadflyContext(plt.plotter, plt) + gplt = getGadflyContext(plt.backend, plt) setGadflyDisplaySize(plt.initargs[1][:size]...) Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt) end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 718b8558..c261e273 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -3,8 +3,8 @@ immutable PyPlotPackage <: PlottingPackage end -export pyplot! -pyplot!() = plotter!(:pyplot) +export pyplot +pyplot() = backend(:pyplot) # ------------------------------- diff --git a/src/backends/qwt.jl b/src/backends/qwt.jl index b229da73..45a77e7a 100644 --- a/src/backends/qwt.jl +++ b/src/backends/qwt.jl @@ -3,8 +3,8 @@ immutable QwtPackage <: PlottingPackage end -export qwt! -qwt!() = plotter!(:qwt) +export qwt +qwt() = backend(:qwt) supportedArgs(::QwtPackage) = setdiff(_allArgs, [:xlims, :ylims, :xticks, :yticks]) supportedTypes(::QwtPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar] diff --git a/src/backends/template.jl b/src/backends/template.jl index 2bf2a3e6..aa1acd42 100644 --- a/src/backends/template.jl +++ b/src/backends/template.jl @@ -5,8 +5,8 @@ immutable [PkgName]Package <: PlottingPackage end -export [pkgname]! -[pkgname]!() = plotter!(:[pkgname]) +export [pkgname] +[pkgname]() = backend(:[pkgname]) # --------------------------------------------------------------------------- diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 54be4cd5..62ad5f21 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -3,8 +3,8 @@ immutable UnicodePlotsPackage <: PlottingPackage end -export unicodeplots! -unicodeplots!() = plotter!(:unicodeplots) +export unicodeplots +unicodeplots() = backend(:unicodeplots) # ------------------------------- diff --git a/src/backends/winston.jl b/src/backends/winston.jl index 9d2fd903..547cbc24 100644 --- a/src/backends/winston.jl +++ b/src/backends/winston.jl @@ -5,8 +5,8 @@ immutable WinstonPackage <: PlottingPackage end -export winston! -winston!() = plotter!(:winston) +export winston +winston() = backend(:winston) # --------------------------------------------------------------------------- diff --git a/src/colors.jl b/src/colors.jl index 722dac20..0b6073f4 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -143,7 +143,7 @@ function handlePlotColors(::PlottingPackage, d::Dict) else bgcolor = _plotDefaults[:background_color] if d[:background_color] != _plotDefaults[:background_color] - warn("Cannot set background_color with backend $(plotter())") + warn("Cannot set background_color with backend $(backend())") end end d[:background_color] = bgcolor diff --git a/src/plot.jl b/src/plot.jl index 8d2d3b40..e5e28979 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -6,18 +6,18 @@ const CURRENT_PLOT = CurrentPlot(Nullable{PlottingObject}()) isplotnull() = isnull(CURRENT_PLOT.nullableplot) -function currentPlot() +function current() if isplotnull() error("No current plot/subplot") end get(CURRENT_PLOT.nullableplot) end -currentPlot!(plot::PlottingObject) = (CURRENT_PLOT.nullableplot = Nullable(plot)) +current(plot::PlottingObject) = (CURRENT_PLOT.nullableplot = Nullable(plot)) # --------------------------------------------------------- -Base.string(plt::Plot) = "Plot{$(plt.plotter) n=$(plt.n)}" +Base.string(plt::Plot) = "Plot{$(plt.backend) n=$(plt.n)}" Base.print(io::IO, plt::Plot) = print(io, string(plt)) Base.show(io::IO, plt::Plot) = print(io, string(plt)) @@ -32,8 +32,8 @@ doc""" The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one: ``` - plot(args...; kw...) # creates a new plot window, and sets it to be the currentPlot - plot!(args...; kw...) # adds to the `currentPlot` + plot(args...; kw...) # creates a new plot window, and sets it to be the current + plot!(args...; kw...) # adds to the `current` plot!(plotobj, args...; kw...) # adds to the plot `plotobj` ``` @@ -43,7 +43,7 @@ When you pass in matrices, it splits by columns. See the documentation for more # this creates a new plot with args/kw and sets it to be the current plot function plot(args...; kw...) - pkg = plotter() + pkg = backend() d = Dict(kw) replaceAliases!(d, _keyAliases) @@ -59,15 +59,15 @@ function plot(args...; kw...) end -function plot_display(args...; kw...) - plt = plot(args...; kw...) - display(plt) - plt -end +# function plot_display(args...; kw...) +# plt = plot(args...; kw...) +# display(plt) +# plt +# end # this adds to the current plot function plot!(args...; kw...) - plot!(currentPlot(), args...; kw...) + plot!(current(), args...; kw...) end # not allowed: @@ -81,14 +81,14 @@ function plot!(plt::Plot, args...; kw...) d = Dict(kw) replaceAliases!(d, _keyAliases) - warnOnUnsupportedArgs(plt.plotter, d) + warnOnUnsupportedArgs(plt.backend, d) # TODO: handle a "group by" mechanism. # will probably want to check for the :group kw param, and split into # index partitions/filters to be passed through to the next step. # Ideally we don't change the insides ot createKWargsList too much to # save from code repetition. We could consider adding a throw - groupargs = haskey(d, :group) ? [extractGroupArgs(d[:group], args...)] : [] + groupargs = get(d, :group, nothing) == nothing ? [] : [extractGroupArgs(d[:group], args...)] # @show groupargs # just in case the backend needs to set up the plot (make it current or something) @@ -110,7 +110,7 @@ function plot!(plt::Plot, args...; kw...) setTicksFromStringVector(d, di, :y, :yticks) # println("Plotting: ", di) - plot!(plt.plotter, plt; di...) + plot!(plt.backend, plt; di...) end @@ -118,7 +118,7 @@ function plot!(plt::Plot, args...; kw...) # add title, axis labels, ticks, etc updatePlotItems(plt, d) - currentPlot!(plt) + current(plt) # NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement # # do we want to show it? @@ -153,7 +153,7 @@ preparePlotUpdate(plt::Plot) = nothing # should we update the x/y label given the meta info during input slicing? function updateDictWithMeta(d::Dict, initargs::Dict, meta::Symbol, isx::Bool) lsym = isx ? :xlabel : :ylabel - if initargs[lsym] == plotDefault(lsym) + if initargs[lsym] == default(lsym) d[lsym] = string(meta) end end @@ -254,7 +254,7 @@ function createKWargsList(plt::PlottingObject, x, y; kw...) # build the series arg dict numUncounted = get(d, :numUncounted, 0) n = plt.n + i + numUncounted - d = getSeriesArgs(plt.plotter, getinitargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n) + d = getSeriesArgs(plt.backend, getinitargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n) d[:x], d[:y] = computeXandY(xs[mod1(i,mx)], ys[mod1(i,my)]) if haskey(d, :idxfilter) @@ -343,7 +343,7 @@ end # -------------------------------------------------------------------- "For DataFrame support. Imports DataFrames and defines the necessary methods which support them." -function dataframes!() +function dataframes() @eval import DataFrames @eval function createKWargsList(plt::PlottingObject, df::DataFrames.DataFrame, args...; kw...) diff --git a/src/plotter.jl b/src/plotter.jl index b3bf8bc7..e700e8d7 100644 --- a/src/plotter.jl +++ b/src/plotter.jl @@ -28,7 +28,7 @@ const INITIALIZED_BACKENDS = Set{Symbol}() backends() = BACKENDS -function backend(sym::Symbol) +function backendInstance(sym::Symbol) sym == :qwt && return QwtPackage() sym == :gadfly && return GadflyPackage() sym == :unicodeplots && return UnicodePlotsPackage() @@ -43,7 +43,7 @@ type CurrentBackend sym::Symbol pkg::PlottingPackage end -CurrentBackend(sym::Symbol) = CurrentBackend(sym, backend(sym)) +CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym)) # --------------------------------------------------------- @@ -90,7 +90,7 @@ end doc""" Returns the current plotting package name. Initializes package on first call. """ -function plotter() +function backend() currentBackendSymbol = CURRENT_BACKEND.sym if !(currentBackendSymbol in INITIALIZED_BACKENDS) @@ -149,7 +149,7 @@ function plotter() end else - error("Unknown plotter $currentBackendSymbol. Choose from: $BACKENDS") + error("Unknown backend $currentBackendSymbol. Choose from: $BACKENDS") end push!(INITIALIZED_BACKENDS, currentBackendSymbol) # println("[Plots.jl] done.") @@ -161,7 +161,7 @@ end doc""" Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots """ -function plotter!(modname) +function backend(modname) # set the PlottingPackage if modname == :qwt @@ -177,7 +177,7 @@ function plotter!(modname) elseif modname == :winston CURRENT_BACKEND.pkg = WinstonPackage() else - error("Unknown plotter $modname. Choose from: $BACKENDS") + error("Unknown backend $modname. Choose from: $BACKENDS") end # update the symbol diff --git a/src/subplot.jl b/src/subplot.jl index 8876a5fe..73c15e9f 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -37,7 +37,7 @@ Base.length(layout::SubplotLayout) = layout.numplts # ------------------------------------------------------------ -Base.string(subplt::Subplot) = "Subplot{$(subplt.plotter) p=$(subplt.p) n=$(subplt.n)}" +Base.string(subplt::Subplot) = "Subplot{$(subplt.backend) p=$(subplt.p) n=$(subplt.n)}" Base.print(io::IO, subplt::Subplot) = print(io, string(subplt)) Base.show(io::IO, subplt::Subplot) = print(io, string(subplt)) @@ -63,17 +63,19 @@ function subplot(args...; kw...) replaceAliases!(d, _keyAliases) # figure out the layout - if haskey(d, :layout) - layout = SubplotLayout(d[:layout]) + layoutarg = get(d, :layout, nothing) + # if haskey(d, :layout) + if layoutarg != nothing + layout = SubplotLayout(layoutarg) else - if !haskey(d, :n) + if !haskey(d, :n) || d[:n] < 0 error("You must specify either layout or n when creating a subplot: ", d) end layout = SubplotLayout(d[:n], get(d, :nr, -1), get(d, :nc, -1)) end # initialize the individual plots - pkg = plotter() + pkg = backend() plts = Plot[] ds = Dict[] for i in 1:length(layout) @@ -100,7 +102,7 @@ Adds to a subplot. # current subplot function subplot!(args...; kw...) - subplot!(currentPlot(), args...; kw...) + subplot!(current(), args...; kw...) end @@ -113,7 +115,7 @@ end # # this adds to a specific subplot... most plot commands will flow through here function subplot!(subplt::Subplot, args...; kw...) if !subplotSupported() - error(CURRENT_BACKEND.sym, " does not support the subplot/subplot! commands at this time. Try one of: ", join(filter(pkg->subplotSupported(backend(pkg)), backends()),", ")) + error(CURRENT_BACKEND.sym, " does not support the subplot/subplot! commands at this time. Try one of: ", join(filter(pkg->subplotSupported(backendInstance(pkg)), backends()),", ")) end d = Dict(kw) @@ -122,12 +124,15 @@ function subplot!(subplt::Subplot, args...; kw...) delete!(d, k) end - kwList = createKWargsList(subplt, args...; d...) - for (i,d) in enumerate(kwList) + kwList, xmeta, ymeta = createKWargsList(subplt, args...; d...) + + # TODO: something useful with meta info? + + for (i,di) in enumerate(kwList) subplt.n += 1 plt = getplot(subplt) # get the Plot object where this series will be drawn - d[:show] = false - plot!(plt; d...) + di[:show] = false + plot!(plt; di...) end # create the underlying object (each backend will do this differently) @@ -137,16 +142,12 @@ function subplot!(subplt::Subplot, args...; kw...) end # set this to be current - currentPlot!(subplt) + current(subplt) - # NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement - # # do we want to show it? - # d = Dict(kw) - # @show d - # if haskey(d, :show) && d[:show] - # println("here...why?") - # display(subplt) - # end + # show it automatically? + if haskey(d, :show) && d[:show] + gui() + end subplt end diff --git a/src/types.jl b/src/types.jl index 1afbc381..19d20f98 100644 --- a/src/types.jl +++ b/src/types.jl @@ -9,7 +9,7 @@ abstract PlottingObject{T<:PlottingPackage} type Plot{T<:PlottingPackage} <: PlottingObject{T} o # the underlying object - plotter::T + backend::T n::Int # number of series # store these just in case @@ -27,7 +27,7 @@ end type Subplot{T<:PlottingPackage} <: PlottingObject{T} o # the underlying object plts::Vector{Plot} # the individual plots - plotter::T + backend::T p::Int # number of plots n::Int # number of series layout::SubplotLayout diff --git a/test/runtests.jl b/test/runtests.jl index a7ccb9ef..aab1f787 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,15 +4,15 @@ using Plots using FactCheck # don't actually show the plots -plotDefault!(:show, false) +default(show=false) srand(1234) # note: we wrap in a try block so that the tests only run if we have the backend installed try Pkg.installed("Gadfly") facts("Gadfly") do - @fact plotter!(:gadfly) --> Plots.GadflyPackage() - @fact plotter() --> Plots.GadflyPackage() + @fact backend(:gadfly) --> Plots.GadflyPackage() + @fact backend() --> Plots.GadflyPackage() @fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyPackage} @@ -41,35 +41,35 @@ end try Pkg.installed("Qwt") facts("Qwt") do - @fact plotter!(:qwt) --> Plots.QwtPackage() - @fact plotter() --> Plots.QwtPackage() + @fact backend(:qwt) --> Plots.QwtPackage() + @fact backend() --> Plots.QwtPackage() @fact typeof(plot(1:10)) --> Plots.Plot{Plots.QwtPackage} # plot(y::AVec; kw...) # one line... x = 1:length(y) @fact plot(1:10) --> not(nothing) - @fact length(currentPlot().o.lines) --> 1 + @fact length(current().o.lines) --> 1 # plot(x::AVec, f::Function; kw...) # one line, y = f(x) @fact plot(1:10, sin) --> not(nothing) - @fact currentPlot().o.lines[1].y --> sin(collect(1:10)) + @fact current().o.lines[1].y --> sin(collect(1:10)) # plot(x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ) @fact plot(rand(10,2), sin) --> not(nothing) - @fact length(currentPlot().o.lines) --> 2 + @fact length(current().o.lines) --> 2 # plot(y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1) @fact plot!(rand(10,2)) --> not(nothing) - @fact length(currentPlot().o.lines) --> 4 + @fact length(current().o.lines) --> 4 # plot(x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ) @fact plot(1:10, Function[sin,cos]) --> not(nothing) - @fact currentPlot().o.lines[1].y --> sin(collect(1:10)) - @fact currentPlot().o.lines[2].y --> cos(collect(1:10)) + @fact current().o.lines[1].y --> sin(collect(1:10)) + @fact current().o.lines[2].y --> cos(collect(1:10)) # plot(y::AVec{AVec}; kw...) # multiple lines, each with x = 1:length(y[i]) @fact plot([11:20 ; rand(10)]) --> not(nothing) - @fact currentPlot().o.lines[1].x[4] --> 4 - @fact currentPlot().o.lines[1].y[4] --> 14 + @fact current().o.lines[1].x[4] --> 4 + @fact current().o.lines[1].y[4] --> 14 end end