diff --git a/docs/src/userguide.md b/docs/src/userguide.md index e51f41415..a2822484f 100644 --- a/docs/src/userguide.md +++ b/docs/src/userguide.md @@ -159,7 +159,7 @@ run(mymodel) ![Explorer Model Example](figs/explorer_model_example.png) -Alternatively, in order to view just one parameter or variable, call the function `explore` as below to return a plot object and automatically display the plot in a viewer, assuming `explore` is the last command executed. This call will return the type `VegaLite.VLSpec`, which you may interact with using the API described in the [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) documentation. For example, [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) plots can be saved as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. You may save a plot using the `save` function. Note that saving an interactive plot in a non-interactive file format, such as .pdf or .svg will result in a warning `WARN Can not resolve event source: window`, but the plot will be saved as a static image. If you wish to preserve interactive capabilities, you may save it using the .vegalite file extension. If you then open this file in Jupyter lab, the interactive aspects will be preserved. +Alternatively, in order to view just one parameter or variable, call the function `explore` as below to return a plot object and automatically display the plot in a viewer, assuming `explore` is the last command executed. This call will return the type `VegaLite.VLSpec`, which you may interact with using the API described in the [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) documentation. For example, [VegaLite.jl](https://github.com/fredo-dedup/VegaLite.jl) plots can be saved as [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics), [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics), [PDF](https://en.wikipedia.org/wiki/PDF) and [EPS](https://en.wikipedia.org/wiki/Encapsulated_PostScript) files. You may save a plot using the `save` function. Note that while `explore(m)` returns interactive plots for line graphs, `explore(m, :foo, :bar)` will return only static plots. ```julia using VegaLite @@ -168,8 +168,6 @@ p = explore(mymodel, component1, parameter1) save("figure.svg", p) ``` -![Explorer Single Plot Example](figs/explorer_single_plot_example.png) - ## Sensitivity Analysis (SA) Support Mimi includes a host of routines which support running various sensitivity analysis methods on Mimi models. The best current documentation on the SA API is the internals documentation [here](internals/montecarlo.md), which provides a working, although informal, description of the SA support of Mimi. This file should be used in conjunction with the examples in [Tutorial 4: Sensitivity Analysis (SA) Support](@ref), since the documentation covers more advanced options such as non-stochastic scenarios and running multiple models, which are not yet included in this tutorial. diff --git a/src/explorer/buildspecs.jl b/src/explorer/buildspecs.jl index ffcd7530f..fadf21797 100644 --- a/src/explorer/buildspecs.jl +++ b/src/explorer/buildspecs.jl @@ -7,7 +7,7 @@ function dataframe_or_scalar(m::Model, comp_name::Symbol, item_name::Symbol) end # Generate the VegaLite spec for a variable or parameter -function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol) +function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol; interactive::Bool=true) dims = dimensions(m, comp_name, item_name) # Control flow logic selects the correct plot type based on dimensions @@ -32,9 +32,9 @@ function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol) # a 'time' field necessitates a line plot elseif dffields[1] == "time" if length(dffields) > 2 - spec = createspec_multilineplot(name, df, dffields) + spec = createspec_multilineplot(name, df, dffields, interactive=interactive) else - spec = createspec_lineplot(name, df, dffields) + spec = createspec_lineplot(name, df, dffields, interactive=interactive) end #otherwise we are dealing with a barplot @@ -88,7 +88,11 @@ global const _plot_width = 450 global const _plot_height = 410 global const _slider_height = 90 -function createspec_lineplot(name, df, dffields) +function createspec_lineplot(name, df, dffields; interactive::Bool=true) + interactive ? createspec_lineplot_interactive(name, df, dffields) : createspec_lineplot_static(name, df, dffields) +end + +function createspec_lineplot_interactive(name, df, dffields) datapart = getdatapart(df, dffields, :line) #returns JSONtext type spec = Dict( "name" => name, @@ -141,7 +145,40 @@ function createspec_lineplot(name, df, dffields) return spec end -function createspec_multilineplot(name, df, dffields) +function createspec_lineplot_static(name, df, dffields) + datapart = getdatapart(df, dffields, :line) #returns JSONtext type + spec = Dict( + "name" => name, + "type" => "line", + "VLspec" => Dict( + "\$schema" => "https://vega.github.io/schema/vega-lite/v2.0.json", + "description" => "plot for a specific component variable pair", + "title" => name, + "data"=> Dict("values" => datapart), + "mark" => Dict("type" => "line"), + "encoding" => Dict( + "x" => Dict( + "field" => dffields[1], + "type" => "temporal", + "timeUnit" => "utcyear", + ), + "y" => Dict( + "field" => dffields[2], + "type" => "quantitative", + ) + ), + "width" => _plot_width, + "height" => _plot_height, + ) + ) + return spec +end + +function createspec_multilineplot(name, df, dffields; interactive::Bool=true) + interactive ? createspec_multilineplot_interactive(name, df, dffields) : createspec_multilineplot_static(name, df, dffields) +end + +function createspec_multilineplot_interactive(name, df, dffields) datapart = getdatapart(df, dffields, :multiline) #returns JSONtext type spec = Dict( "name" => name, @@ -197,6 +234,37 @@ function createspec_multilineplot(name, df, dffields) return spec end +function createspec_multilineplot_static(name, df, dffields) + datapart = getdatapart(df, dffields, :multiline) #returns JSONtext type + spec = Dict( + "name" => name, + "VLspec" => Dict( + "\$schema" => "https://vega.github.io/schema/vega-lite/v2.0.json", + "description" => "plot for a specific component variable pair", + "title" => name, + "data" => Dict("values" => datapart), + + "mark" => Dict("type" => "line"), + "encoding" => Dict( + "x" => Dict( + "field" => dffields[1], + "type" => "temporal", + "timeUnit" => "utcyear", + ), + "y" => Dict( + "field" => dffields[3], + "type" => "quantitative", + ), + "color" => Dict("field" => dffields[2], "type" => "nominal", + "scale" => Dict("scheme" => "category20")), + ), + "width" => _plot_width, + "height" => _plot_height + ), + ) + return spec +end + function createspec_barplot(name, df, dffields) datapart = getdatapart(df, dffields, :bar) #returns JSONtext type spec = Dict( @@ -253,7 +321,6 @@ function getdatapart(df, dffields, plottype::Symbol) return JSON.JSONText(datapart) end - function getmultiline(cols, dffields) datasb = StringBuilder() numrows = length(cols[1]) diff --git a/src/explorer/explore.jl b/src/explorer/explore.jl index 880602e04..f8e25414c 100644 --- a/src/explorer/explore.jl +++ b/src/explorer/explore.jl @@ -52,7 +52,7 @@ function explore(m::Model; title = "Electron") end """ - explore(m::Model, comp_name::Symbol, datum_name::Symbol) + explore(m::Model, comp_name::Symbol, datum_name::Symbol; interactive::String=true) Plot a specific `datum_name` (a `variable` or `parameter`) of Model `m`. """ @@ -62,7 +62,7 @@ function explore(m::Model, comp_name::Symbol, datum_name::Symbol) error("A model must be run before it can be plotted") end - spec = Mimi._spec_for_item(m, comp_name, datum_name)["VLspec"] + spec = Mimi._spec_for_item(m, comp_name, datum_name, interactive=false)["VLspec"] spec === nothing && error("Spec cannot be built.") return VegaLite.VLSpec{:plot}(spec) diff --git a/test/test_explorer.jl b/test/test_explorer.jl index 462123cb0..15d978d2a 100644 --- a/test/test_explorer.jl +++ b/test/test_explorer.jl @@ -63,6 +63,7 @@ s = menu_item_list(m) #4. explore(m::Model, title = "Electron") w = explore(m, title = "Testing Window") @test typeof(w) == Electron.Window +close(w) #5. explore(m::Model, comp_name::Symbol, datum_name::Symbol; # dim_name::Union{Nothing, Symbol} = nothing)