diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..4b3c345 --- /dev/null +++ b/Project.toml @@ -0,0 +1,25 @@ +name = "Plotly" +uuid = "58dd65bb-95f3-509e-9936-c39a10fdeae7" +version = "0.4.1" + +[deps] +Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" + +[compat] +HTTP = "0.9" +JSON = "0.21" +PlotlyJS = "0.15, 0.16, 0.17, 0.18" +Reexport = "1.0" +julia = "1.4" + +[extras] +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["JSON", "Test"] diff --git a/README.md b/README.md index a5e30c2..d9bba1d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,13 @@ [![Build Status](https://travis-ci.org/plotly/Plotly.jl.svg)](https://travis-ci.org/plotly/Plotly.jl) -> A Julia interface to the plot.ly plotting library and cloud services +A Julia interface to the plot.ly plotting library and cloud services + +
+ + Maintained by the Plotly Community + +
## Install @@ -10,7 +16,7 @@ Simply run `Pkg.add("Plotly")`. ## Usage -Plotting functions provided by this package are identical to [PlotlyJS](https://github.com/spencerlyon2/PlotlyJS.jl). Please consult its [documentation](http://spencerlyon.com/PlotlyJS.jl/). +Plotting functions provided by this package are identical to [PlotlyJS](https://github.com/spencerlyon2/PlotlyJS.jl). Please consult its [documentation](http://spencerlyon.com/PlotlyJS.jl/). In fact, the package depends on `PlotlyJS.jl` and reexports all the methods. For example, this will display a basic scatter plot: @@ -70,6 +76,16 @@ local_plot = download(RemotePlot("https://plot.ly/~malmaud/73")) # or equivalently, local_plot = download_plot("https://plot.ly/~malmaud/73") ``` +## Working with `plotlyjs()` backend of `Plots.jl` + +A plot created by `Plots.jl` with `plotlyjs()` backend has the type `Plot{Plots.PlotlyJSBackend()}`. +To use the `Plotly.jl` interfeces, the plot object needs to be converted by +```julia +my_plot = Plots.plotlyjs_syncplot(plots_plot) +``` +The object `my_plot` can be handed to the Cloud API descrived above. + + ## Acknowledgements [PlotlyJS.jl ](https://github.com/spencerlyon2/PlotlyJS.jl), which provides the large majority of the functionality of this package, is developed primarily by Spencer Lyon. diff --git a/create_src_attrs.jl b/create_src_attrs.jl new file mode 100644 index 0000000..41bc21a --- /dev/null +++ b/create_src_attrs.jl @@ -0,0 +1,52 @@ +module AttrGroups + +using JSON +using HTTP +using DelimitedFiles + +_symbol_dict(x) = x +_symbol_dict(d::AbstractDict) = + Dict{Symbol,Any}([(Symbol(k), _symbol_dict(v)) for (k, v) in d]) + +function main() + + url = "https://api.plot.ly/v2/plot-schema?sha1" + data = _symbol_dict(JSON.parse(String(HTTP.get(url).body))["schema"]) + + nms = Set{Symbol}() + function add_to_names!(d::AbstractDict) + foreach(add_to_names!, keys(d)) + foreach(add_to_names!, values(d)) + nothing + end + add_to_names!(s::Symbol) = push!(nms, s) + add_to_names!(x) = nothing + + add_to_names!(data[:layout][:layoutAttributes]) + for (_, v) in data[:traces] + add_to_names!(v) + end + + _UNDERSCORE_ATTRS = collect( + filter( + x -> occursin(string(x), "_") && !startswith(string(x), "_"), + nms + ) + ) + + _SRC_ATTRS = collect(filter(x -> endswith(string(x), "src"), nms)) + + open(joinpath(@__DIR__, "src", "src_attrs.csv"), "w") do f + writedlm(f, map(string, _SRC_ATTRS)) + end + + open(joinpath(@__DIR__, "src", "underscore_attrs.csv"), "w") do f + writedlm(f, map(string, _UNDERSCORE_ATTRS)) + end + + _UNDERSCORE_ATTRS, _SRC_ATTRS +end + + + +end # module diff --git a/src/Plotly.jl b/src/Plotly.jl index 80ec5bb..560ae07 100644 --- a/src/Plotly.jl +++ b/src/Plotly.jl @@ -4,14 +4,14 @@ using HTTP using Reexport using JSON @reexport using PlotlyJS -using DelimitedFiles, Pkg, Base64 # stdlib +using DelimitedFiles, Base64 # stdlib export set_credentials_file, RemotePlot, download_plot, savefig_remote, post const _SRC_ATTRS = let - _src_attr_path = joinpath(PlotlyJS._pkg_root, "deps", "src_attrs.csv") + _src_attr_path = joinpath(@__DIR__, "src_attrs.csv") raw_src_attrs = vec(readdlm(_src_attr_path)) - src_attrs = map(x -> x[1:end-3], raw_src_attrs) # remove the `src` suffix + src_attrs = map(x -> x[1:end - 3], raw_src_attrs) # remove the `src` suffix Set(map(Symbol, src_attrs)) end::Set{Symbol} @@ -99,12 +99,12 @@ function post_v2(p::Plot; fileopt=get_config().fileopt, filename=nothing, kwargs end end -function post(p::Plot; kwargs...) +function HTTP.post(p::Plot; kwargs...) # call JSON.lower to apply themes JSON.lower(p) config = get_config() - default_kwargs = Dict{Symbol,Any}(:filename=>"Plot from Julia API", - :world_readable=> config.world_readable) + default_kwargs = Dict{Symbol,Any}(:filename => "Plot from Julia API", + :world_readable => config.world_readable) default_opts = Dict{Symbol,Any}(:origin => "plot", :platform => "Julia", :version => "0.2") @@ -140,7 +140,7 @@ function post(p::Plot; kwargs...) return RemotePlot(HTTP.URI(body["url"])) end -post(p::PlotlyJS.SyncPlot; kwargs...) = post(p.plot; kwargs...) +HTTP.post(p::PlotlyJS.SyncPlot; kwargs...) = post(p.plot; kwargs...) post_v2(p::PlotlyJS.SyncPlot; kwargs...) = post_v2(p.plot; kwargs...) """ @@ -238,7 +238,7 @@ function srcify!(p::Plot; fileopt::Symbol=get_config().fileopt, grid_fn=nothing, if fileopt == :create || fileopt == :new # add order to each grid for (i, (k, v)) in enumerate(data_for_grid) - v["order"] = i-1 + v["order"] = i - 1 end parent_path = dirname(grid_fn) if !isempty(parent_path) @@ -268,11 +268,11 @@ function srcify!(p::Plot; fileopt::Symbol=get_config().fileopt, grid_fn=nothing, uid = uid_map[k] if key[1] == "trace" trace_ind = key[2] - the_key = join(vcat(key[3:end-1], string(key[end], "src")), "_") + the_key = join(vcat(key[3:end - 1], string(key[end], "src")), "_") col_uid = string(fid, ":", uid) p.data[trace_ind][the_key] = col_uid elseif key[1] == "layout" - the_key = join(vcat(key[2:end-1], string(key[end], "src")), "_") + the_key = join(vcat(key[2:end - 1], string(key[end], "src")), "_") col_uid = string(fid, ":", uid) p.layout[the_key] = col_uid else @@ -325,7 +325,7 @@ function savefig_remote(p::Plot, fn::String; width::Int=8, height::Int=6) end if suf in ["png", "jpeg", "svg", "pdf", "eps", "webp"] - res = image_generate(p, format=suf, width=width*96, height=height*96) + res = image_generate(p, format=suf, width=width * 96, height=height * 96) open(fn, "w") do f print(f, String(res)) end diff --git a/src/src_attrs.csv b/src/src_attrs.csv new file mode 100644 index 0000000..4724cf8 --- /dev/null +++ b/src/src_attrs.csv @@ -0,0 +1,85 @@ +xysrc +arraysrc +opensrc +ticktextsrc +lowerfencesrc +textpositionsrc +rsrc +bgcolorsrc +tsrc +colorsrc +familysrc +upperfencesrc +hoverinfosrc +thetasrc +asrc +xboundssrc +xsrc +vsrc +labelssrc +alignsrc +hovertemplatesrc +highsrc +usrc +prefixsrc +arrayminussrc +labelsrc +typesrc +q1src +meansrc +csrc +isrc +locationssrc +valuessrc +wsrc +widthsrc +q3src +indicessrc +parentssrc +vertexcolorsrc +idssrc +texttemplatesrc +metasrc +jsrc +basesrc +namelengthsrc +customdatasrc +tickvalssrc +mediansrc +columnwidthsrc +suffixsrc +valuesrc +surfacecolorsrc +bsrc +sizesrc +facecolorsrc +dashsrc +zsrc +textsrc +sdsrc +sourcesrc +hovertextsrc +bordercolorsrc +formatsrc +columnordersrc +measuresrc +countssrc +closesrc +intensitysrc +hiddenlabelssrc +anglesrc +pullsrc +colorssrc +categoryarraysrc +lowsrc +yboundssrc +lonsrc +targetsrc +radiussrc +offsetsrc +symbolsrc +opacitysrc +notchspansrc +ksrc +ysrc +latsrc diff --git a/src/utils.jl b/src/utils.jl index b39ea32..bed5521 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -40,7 +40,7 @@ function Base.merge(config::PlotlyConfig, other::AbstractDict) ) end -Base.show(io::IO, config::PlotlyConfig) = dump(IOContext(io, :limit=>true), config) +Base.show(io::IO, config::PlotlyConfig) = dump(IOContext(io, :limit => true), config) function Base.Dict(config::PlotlyConfig) Dict(k => getfield(config, k) for k in fieldnames(PlotlyConfig)) @@ -56,8 +56,7 @@ function signin( endpoints::Union{Nothing,AbstractDict}=nothing ) global plotlycredentials = PlotlyCredentials(username, api_key) - - + set_credentials_file(plotlycredentials) # if endpoints are specified both the base and api domains must be # specified @@ -110,6 +109,8 @@ function get_config() return plotlyconfig end +set_credentials_file(pc::PlotlyCredentials) = set_credentials_file(Dict("username" => pc.username, "api_key" => pc.api_key)) + """ set_credentials_file(input_creds::AbstractDict) @@ -155,6 +156,8 @@ function set_config_file(input_config::AbstractDict) end end +set_config_file(;kw...) = set_config_file(Dict(kw...)) + """ set_config_file(config::PlotlyConfig) diff --git a/src/v2.jl b/src/v2.jl index fdffbc3..e2445c6 100644 --- a/src/v2.jl +++ b/src/v2.jl @@ -3,7 +3,6 @@ # ------------- # const API_ROOT = "https://api.plot.ly/v2/" -const _VERSION = string(Pkg.installed()["Plotly"]) import JSON: json import HTTP, JSON import HTTP: post @@ -33,7 +32,7 @@ end function get_req_headers() creds = get_credentials() return Dict{Any,Any}( - "Plotly-Client-Platform" => "Julia $(_VERSION)", + "Plotly-Client-Platform" => "Julia", "Content-Type" => "application/json", "content-type" => "application/json", "Accept" => "application/json", # TODO: for some reason I had to do this to get it to work???