From 4d4ae42347d0bf44194c555b1586a2eddb8f8a72 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 12:50:27 -0700 Subject: [PATCH 1/6] Add scatter plot to explorer --- src/explorer/buildspecs.jl | 30 ++++++++++++++++++++++++++++-- wip/temp.jl | 25 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 wip/temp.jl diff --git a/src/explorer/buildspecs.jl b/src/explorer/buildspecs.jl index 545c43d13..57ddafecf 100644 --- a/src/explorer/buildspecs.jl +++ b/src/explorer/buildspecs.jl @@ -53,9 +53,13 @@ function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol; interact spec = createspec_lineplot(name, df, dffields, interactive=interactive) end - #otherwise we are dealing with a barplot + #otherwise we are dealing with a barplot or a scatter plot else - spec = createspec_barplot(name, df, dffields) + if eltypes(df)[1] <: Number + spec = createspec_scatterplot(name, df, dffields) + else + spec = createspec_barplot(name, df, dffields) + end end end @@ -420,6 +424,28 @@ function createspec_barplot(name, df, dffields) return spec end +function createspec_scatter(name, df, dffields) + datapart = getdatapart(df, dffields, :scatter) #returns JSONtext type + spec = Dict( + "name" => name, + "type" => "point", + "VLspec" => Dict( + "\$schema" => "https://vega.github.io/schema/vega-lite/v3.json", + "description" => "plot for a specific component variable pair", + "title" => name, + "data"=> Dict("values" => datapart), + "mark" => "point", + "encoding" => Dict( + "x" => Dict("field" => dffields[1], "type" => "quantitative"), + "y" => Dict("field" => dffields[2], "type" => "quantitative" ) + ), + "width" => _plot_width, + "height" => _plot_height + ) + ) + return spec +end + function createspec_singlevalue(name) datapart = []; diff --git a/wip/temp.jl b/wip/temp.jl new file mode 100644 index 000000000..84915ce2e --- /dev/null +++ b/wip/temp.jl @@ -0,0 +1,25 @@ +using Mimi + +@defcomp example begin + p0 = Parameter(index = [time]) + p1 = Parameter(index = [foo]) + p2 = Parameter(index = [foo, bar]) + p3 = Parameter(index = [foo, baz]) + p4 = Parameter(index = [time, bar]) + p5 = Parameter(index = [time, baz]) +end + +m = Model() +set_dimension!(m, :time, collect(1:10)) +add_comp!(m, example) +set_dimension!(m, :foo, 1:5) +set_dimension!(m, :bar, 1:3) +set_dimension!(m, :baz, [:A, :B, :C]) +set_param!(m, :example, :p0, 1:10) +set_param!(m, :example, :p1, 1:5) +set_param!(m, :example, :p2, reshape(1:15, 5, 3)) +set_param!(m, :example, :p3, reshape(1:15, 5, 3)) +set_param!(m, :example, :p4, reshape(1:30, 10, 3)) +set_param!(m, :example, :p5, reshape(1:30, 10, 3)) +run(m) +explore(m) \ No newline at end of file From f399e18018e9cfe2ad71d43ce2097af068d7cf74 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 13:29:49 -0700 Subject: [PATCH 2/6] Fix syntax --- wip/temp.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wip/temp.jl b/wip/temp.jl index 84915ce2e..144b9e6a4 100644 --- a/wip/temp.jl +++ b/wip/temp.jl @@ -7,14 +7,22 @@ using Mimi p3 = Parameter(index = [foo, baz]) p4 = Parameter(index = [time, bar]) p5 = Parameter(index = [time, baz]) + + x = Variable(index = [time]) + function run_timestep(p,v,d,t) + v.x[t] = 0 + end end m = Model() + set_dimension!(m, :time, collect(1:10)) -add_comp!(m, example) set_dimension!(m, :foo, 1:5) set_dimension!(m, :bar, 1:3) set_dimension!(m, :baz, [:A, :B, :C]) + +add_comp!(m, example) + set_param!(m, :example, :p0, 1:10) set_param!(m, :example, :p1, 1:5) set_param!(m, :example, :p2, reshape(1:15, 5, 3)) From 8fe6d5c3cf65434fc306096e8ec2103e49b2fc79 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 15:49:07 -0700 Subject: [PATCH 3/6] Break up big file; add methods for multi bar and multi scatter --- src/explorer/buildmenu.jl | 103 +++++++++++ src/explorer/buildspecs.jl | 323 ++++++++++------------------------- src/explorer/explore.jl | 2 + src/explorer/getdataparts.jl | 106 ++++++++++++ test/test_explorer_model.jl | 39 +++++ wip/temp.jl | 33 ---- 6 files changed, 342 insertions(+), 264 deletions(-) create mode 100644 src/explorer/buildmenu.jl create mode 100644 src/explorer/getdataparts.jl delete mode 100644 wip/temp.jl diff --git a/src/explorer/buildmenu.jl b/src/explorer/buildmenu.jl new file mode 100644 index 000000000..49d7a624f --- /dev/null +++ b/src/explorer/buildmenu.jl @@ -0,0 +1,103 @@ +## Build menu tree structure for explorer + +function tree_view_values(model::Model) + all_subcomps = [] + for comp_def in compdefs(model) + subcomp = tree_view_values(model, nameof(comp_def), comp_def) + push!(all_subcomps, subcomp) + end + + # Return sorted list so that the UI list of items will be in lexicographic order + return sort(all_subcomps, by = x -> lowercase(x["name"])) +end + +function tree_view_values(model::Model, comp_name::Symbol, comp_def::AbstractComponentDef) + sub_comp_item = _tree_view_node(comp_name) + for subcomp in compdefs(comp_def) + push!(sub_comp_item["children"], tree_view_values(model, nameof(subcomp), subcomp)); + end + return sub_comp_item +end + +function _tree_view_node(comp_name::Symbol) + return Dict("name" => "$comp_name", "children" => Dict[]) +end + +# Create the list of variables and parameters +function menu_item_list(model::Model) + var_menuitems = [] + par_menuitems = [] + + for comp_def in compdefs(model) + all_subcomp_values = menu_item_list(model, nameof(comp_def), comp_def) + append!(var_menuitems, all_subcomp_values["vars"]) + append!(par_menuitems, all_subcomp_values["pars"]) + end + + # Return sorted list so that the UI list of items will be in lexicographic order + return Dict("vars" => sort(var_menuitems, by = x -> lowercase(x["name"])),"pars" => sort(par_menuitems, by = x -> lowercase(x["name"]))) +end + +# Create the list of variables and parameters +function menu_item_list(m::Model, comp_name::Symbol, comp_def::AbstractComponentDef) + var_menu_items = map(var_name -> _menu_item(m, Symbol(comp_name), var_name), variable_names(comp_def)); + par_menu_items = map(par_name -> _menu_item(m, Symbol(comp_name), par_name), parameter_names(comp_def)); + + # Return sorted list so that the UI list of items will be in lexicographic order + return Dict("vars" => sort(var_menu_items, by = x -> lowercase(x["name"])),"pars" => sort(par_menu_items, by = x -> lowercase(x["name"]))) +end + +function menu_item_list(sim_inst::SimulationInstance) + all_menuitems = [] + for datum_key in sim_inst.sim_def.savelist + menu_item = _menu_item(sim_inst, datum_key) + if menu_item !== nothing + push!(all_menuitems, menu_item) + end + end + + # Return sorted list so that the UI list of items will be in lexicographic order + return sort(all_menuitems, by = x -> lowercase(x["name"])) +end + +function _menu_item(m::Model, comp_name::Symbol, item_name::Symbol) + dims = dim_names(m, comp_name, item_name) + if length(dims) > 2 + # Drop references to singleton dimensions + dims = tuple([dim for dim in dims if dim_count(m, dim) != 1]...) + end + + if length(dims) == 0 + paths = _get_all_paths(m) + comp_path = paths[comp_name]; + value = m[comp_path, item_name] + name = "$comp_name : $item_name = $value" + elseif length(dims) > 2 + @warn("$comp_name.$item_name has > 2 indexed dimensions, not yet implemented in explorer") + name = "$comp_name : $item_name (CANNOT DISPLAY)" + else + name = "$comp_name : $item_name" # the name is needed for the list label + end + + menu_item = Dict("name" => name, "comp_name" => comp_name, "item_name" => item_name) + return menu_item +end + +function _menu_item(sim_inst::SimulationInstance, datum_key::Tuple{Symbol, Symbol}) + (comp_name, item_name) = datum_key + dims = dim_names(sim_inst.models[1], comp_name, item_name) + if length(dims) > 2 + # Drop references to singleton dimensions + dims = tuple([dim for dim in dims if dim_count(m, dim) != 1]...) + end + + if length(dims) > 2 + @warn("$comp_name.$item_name has >2 graphing dims, not yet implemented in explorer") + name = "$comp_name : $item_name (CANNOT DISPLAY)" + else + name = "$comp_name : $item_name" # the name is needed for the list label + end + + menu_item = Dict("name" => "$item_name", "comp_name" => comp_name, "item_name" => item_name) + return menu_item +end diff --git a/src/explorer/buildspecs.jl b/src/explorer/buildspecs.jl index 57ddafecf..446fdd906 100644 --- a/src/explorer/buildspecs.jl +++ b/src/explorer/buildspecs.jl @@ -1,17 +1,14 @@ -## Mimi UI -using Dates -using CSVFiles +# Create individual specs -function dataframe_or_scalar(m::Model, comp_name::Symbol, item_name::Symbol) - dims = dim_names(m, comp_name, item_name) - return length(dims) > 0 ? getdataframe(m, comp_name, item_name) : m[comp_name, item_name] -end +# Plot constants +global const _plot_width = 450 +global const _plot_height = 410 +global const _slider_height = 90 ## -## 1. Generate the VegaLite spec for a variable or parameter +## Primary spec functions ## -# Get spec function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol; interactive::Bool=true) dims = dim_names(m, comp_name, item_name) if length(dims) > 2 @@ -21,22 +18,35 @@ function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol; interact # Control flow logic selects the correct plot type based on dimensions # and dataframe fields + + ## + ## No Plot Clases + ## + + # if there are no dimensions we show the values in the label in the menu if length(dims) == 0 paths = _get_all_paths(m) comp_path = paths[comp_name]; value = m[comp_path, item_name] === nothing ? m[comp_name, item_name] : m[comp_path, item_name] name = "$comp_name : $item_name = $value" spec = createspec_singlevalue(name) + + # we do not support over two indexed dimensions right now elseif length(dims) > 2 @warn("$comp_name.$item_name has > 2 indexed dimensions, not yet implemented in explorer") name = "$comp_name : $item_name (CANNOT DISPLAY)" spec = createspec_singlevalue(name) + + ## + ## Plot Cases + ## + else name = "$comp_name : $item_name" df = getdataframe(m, comp_name, item_name) dffields = map(string, names(df)) # convert to string once before creating specs - # a 'time' field necessitates a line plot + # Time is a Dimension - line plots if "time" in dffields # need to reorder the df to have 'time' as the first dimension @@ -52,13 +62,21 @@ function _spec_for_item(m::Model, comp_name::Symbol, item_name::Symbol; interact else spec = createspec_lineplot(name, df, dffields, interactive=interactive) end - - #otherwise we are dealing with a barplot or a scatter plot - else - if eltypes(df)[1] <: Number + + # No Time Dimension and First Dim is a Number Type - scatter plots + elseif eltype(df[1]) <: Number + if length(dffields) > 2 + spec = createspec_multiscatterplot(name, df, dffields) + else spec = createspec_scatterplot(name, df, dffields) + end + + # No Time Dimension and First Dim is Not a Number Type - bar plots + else + if length(dffields) > 2 + spec = createspec_multibarplot(name, df, dffields) else - spec = createspec_barplot(name, df, dffields) + spec = createspec_barplot(name, df, dffields) end end end @@ -111,113 +129,10 @@ function _spec_for_sim_item(sim_inst::SimulationInstance, comp_name::Symbol, ite end -function tree_view_values(model::Model) - all_subcomps = [] - for comp_def in compdefs(model) - subcomp = tree_view_values(model, nameof(comp_def), comp_def) - push!(all_subcomps, subcomp) - end - - # Return sorted list so that the UI list of items will be in lexicographic order - return sort(all_subcomps, by = x -> lowercase(x["name"])) -end - -function tree_view_values(model::Model, comp_name::Symbol, comp_def::AbstractComponentDef) - sub_comp_item = _tree_view_node(comp_name) - for subcomp in compdefs(comp_def) - push!(sub_comp_item["children"], tree_view_values(model, nameof(subcomp), subcomp)); - end - return sub_comp_item -end - -function _tree_view_node(comp_name::Symbol) - return Dict("name" => "$comp_name", "children" => Dict[]) -end - -# Create the list of variables and parameters -function menu_item_list(model::Model) - var_menuitems = [] - par_menuitems = [] - - for comp_def in compdefs(model) - all_subcomp_values = menu_item_list(model, nameof(comp_def), comp_def) - append!(var_menuitems, all_subcomp_values["vars"]) - append!(par_menuitems, all_subcomp_values["pars"]) - end - - # Return sorted list so that the UI list of items will be in lexicographic order - return Dict("vars" => sort(var_menuitems, by = x -> lowercase(x["name"])),"pars" => sort(par_menuitems, by = x -> lowercase(x["name"]))) -end - -# Create the list of variables and parameters -function menu_item_list(m::Model, comp_name::Symbol, comp_def::AbstractComponentDef) - var_menu_items = map(var_name -> _menu_item(m, Symbol(comp_name), var_name), variable_names(comp_def)); - par_menu_items = map(par_name -> _menu_item(m, Symbol(comp_name), par_name), parameter_names(comp_def)); - - # Return sorted list so that the UI list of items will be in lexicographic order - return Dict("vars" => sort(var_menu_items, by = x -> lowercase(x["name"])),"pars" => sort(par_menu_items, by = x -> lowercase(x["name"]))) -end - -function menu_item_list(sim_inst::SimulationInstance) - all_menuitems = [] - for datum_key in sim_inst.sim_def.savelist - menu_item = _menu_item(sim_inst, datum_key) - if menu_item !== nothing - push!(all_menuitems, menu_item) - end - end - - # Return sorted list so that the UI list of items will be in lexicographic order - return sort(all_menuitems, by = x -> lowercase(x["name"])) -end - -function _menu_item(m::Model, comp_name::Symbol, item_name::Symbol) - dims = dim_names(m, comp_name, item_name) - if length(dims) > 2 - # Drop references to singleton dimensions - dims = tuple([dim for dim in dims if dim_count(m, dim) != 1]...) - end - - if length(dims) == 0 - paths = _get_all_paths(m) - comp_path = paths[comp_name]; - value = m[comp_path, item_name] - name = "$comp_name : $item_name = $value" - elseif length(dims) > 2 - @warn("$comp_name.$item_name has > 2 indexed dimensions, not yet implemented in explorer") - name = "$comp_name : $item_name (CANNOT DISPLAY)" - else - name = "$comp_name : $item_name" # the name is needed for the list label - end - - menu_item = Dict("name" => name, "comp_name" => comp_name, "item_name" => item_name) - return menu_item -end - -function _menu_item(sim_inst::SimulationInstance, datum_key::Tuple{Symbol, Symbol}) - (comp_name, item_name) = datum_key - dims = dim_names(sim_inst.models[1], comp_name, item_name) - if length(dims) > 2 - # Drop references to singleton dimensions - dims = tuple([dim for dim in dims if dim_count(m, dim) != 1]...) - end - - if length(dims) > 2 - @warn("$comp_name.$item_name has >2 graphing dims, not yet implemented in explorer") - name = "$comp_name : $item_name (CANNOT DISPLAY)" - else - name = "$comp_name : $item_name" # the name is needed for the list label - end - - menu_item = Dict("name" => "$item_name", "comp_name" => comp_name, "item_name" => item_name) - return menu_item -end - ## -## 2. Create individual specs +## Methods for explore(m::model) ## -# Specs for explore(m::Model) function createspec_lineplot(name, df, dffields; interactive::Bool=true) interactive ? createspec_lineplot_interactive(name, df, dffields) : createspec_lineplot_static(name, df, dffields) end @@ -424,7 +339,31 @@ function createspec_barplot(name, df, dffields) return spec end -function createspec_scatter(name, df, dffields) +function createspec_multibarplot(name, df, dffields) + datapart = getdatapart(df, dffields, :multibar) + spec = Dict( + "name" => name, + "type" => "bar", + "VLspec" => Dict( + "\$schema" => "https://vega.github.io/schema/vega-lite/v3.json", + "description" => "plot for a specific component variable pair", + "title" => name, + "data"=> Dict("values" => datapart), + "mark" => "bar", + "encoding" => Dict( + "x" => Dict("field" => dffields[1], "type" => "ordinal"), + "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_scatterplot(name, df, dffields) datapart = getdatapart(df, dffields, :scatter) #returns JSONtext type spec = Dict( "name" => name, @@ -446,6 +385,31 @@ function createspec_scatter(name, df, dffields) return spec end +function createspec_multiscatterplot(name, df, dffields) + datapart = getdatapart(df, dffields, :multiscatter) + spec = Dict( + "name" => name, + "type" => "point", + "VLspec" => Dict( + "\$schema" => "https://vega.github.io/schema/vega-lite/v3.json", + "description" => "plot for a specific component variable pair", + "title" => name, + "data"=> Dict("values" => datapart), + "mark" => "point", + "encoding" => Dict( + "x" => Dict("field" => dffields[1], "type" => "quantitative"), + "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_singlevalue(name) datapart = []; @@ -457,7 +421,9 @@ function createspec_singlevalue(name) return spec end -# Specs for explore(sim_inst::SimulationInstance) +## +## Methods for explore(sim_inst::SimulationInstance) +## function createspec_trumpet(name, df, dffields; interactive::Bool=true) df_reduced = trumpet_df_reduce(df, :trumpet) #reduce the dataframe down to only the data needed for max, min, and mean lines @@ -987,118 +953,13 @@ function createspec_multihistogram_interactive(name, df, dffields) return spec end -# Plot constants -global const _plot_width = 450 -global const _plot_height = 410 -global const _slider_height = 90 - ## -## Helper functions +## Helpers ## -# Various functions to get the JSONtext of the data -function getdatapart(df, dffields, plottype::Symbol) - - # start the main string - sb = StringBuilder() - append!(sb, "["); - - # get the specific string for this type of data - datasb = StringBuilder() - numrows = length(df[!, 1]); - - # loop over rows and create a dictionary for each row - if plottype == :multitrumpet #4D with 3 indices - cols = (df[!, 1], df[!, 2], df[!, 3], df[!, 4]) - datastring = getdatapart_4d(cols, dffields, numrows, datasb) - elseif plottype == :multiline || plottype == :trumpet #3D with 2 indices, one of which is time - cols = (df[!, 1], df[!, 2], df[!, 3]) - datastring = getdatapart_3d_time(cols, dffields, numrows, datasb) - elseif plottype == :multihistogram #3D with 2 indices, none of which is time - cols = (df[!, 1], df[!, 2], df[!, 3]) - datastring = getdatapart_3d(cols, dffields, numrows, datasb) - elseif plottype == :line #2D with 1 index, one of which is time - cols = (df[!, 1], df[!, 2]) - datastring = getdatapart_2d_time(cols, dffields, numrows, datasb) - else # :bar and :histogram - cols = (df[!, 1], df[!, 2]) - datastring = getdatapart_2d(cols, dffields, numrows, datasb) - end - - append!(sb, datastring * "]"); - datapart = String(sb) - - return JSON.JSONText(datapart) -end - -function getdatapart_4d(cols, dffields, numrows, datasb) - for i = 1:numrows - - append!(datasb, "{ - \"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) * "\", - \"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\", - \"" * dffields[3] * "\":\"" * string(cols[3][i]) * "\", - \"" * dffields[4] * "\":\"" * string(cols[4][i]) * "\"}") - - if i != numrows - append!(datasb, ",") - end - end - return String(datasb) -end - -function getdatapart_3d_time(cols, dffields, numrows, datasb) - for i = 1:numrows - - append!(datasb, "{\"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) - * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\",\"" - * dffields[3] * "\":\"" * string(cols[3][i]) * "\"}") - - if i != numrows - append!(datasb, ",") - end - end - return String(datasb) -end - -function getdatapart_3d(cols, dffields, numrows, datasb) - for i = 1:numrows - - append!(datasb, "{\"" * dffields[1] * "\":\"" * string(cols[1][i]) - * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\",\"" - * dffields[3] * "\":\"" * string(cols[3][i]) * "\"}") - - if i != numrows - append!(datasb, ",") - end - end - return String(datasb) -end - -function getdatapart_2d_time(cols, dffields, numrows, datasb) - for i = 1:numrows - append!(datasb, "{\"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) - * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\"}") - - if i != numrows - append!(datasb, ",") - end - end - - return String(datasb) -end - -function getdatapart_2d(cols, dffields, numrows, datasb) - for i = 1:numrows - - append!(datasb, "{\"" * dffields[1] * "\":\"" * string(cols[1][i]) * - "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\"}") #end of dictionary - - if i != numrows - append!(datasb, ",") - end - end - return String(datasb) +function dataframe_or_scalar(m::Model, comp_name::Symbol, item_name::Symbol) + dims = dim_names(m, comp_name, item_name) + return length(dims) > 0 ? getdataframe(m, comp_name, item_name) : m[comp_name, item_name] end function trumpet_df_reduce(df, plottype::Symbol) @@ -1128,4 +989,4 @@ function trumpet_df_reduce(df, plottype::Symbol) end return df_new[:, reorder_cols] -end +end \ No newline at end of file diff --git a/src/explorer/explore.jl b/src/explorer/explore.jl index 7ffa7486f..63a7daa0a 100644 --- a/src/explorer/explore.jl +++ b/src/explorer/explore.jl @@ -7,7 +7,9 @@ export save global app = nothing #include functions and modules +include("getdataparts.jl") include("buildspecs.jl") +include("buildmenu.jl") include("results.jl") """ diff --git a/src/explorer/getdataparts.jl b/src/explorer/getdataparts.jl new file mode 100644 index 000000000..26c3c899d --- /dev/null +++ b/src/explorer/getdataparts.jl @@ -0,0 +1,106 @@ +using Dates + +# Various functions to get the JSONtext of the data +function getdatapart(df, dffields, plottype::Symbol) + + # start the main string + sb = StringBuilder() + append!(sb, "["); + + # get the specific string for this type of data + datasb = StringBuilder() + numrows = length(df[!, 1]); + + # loop over rows and create a dictionary for each row + if plottype == :multitrumpet #4D with 3 indices + cols = (df[!, 1], df[!, 2], df[!, 3], df[!, 4]) + datastring = getdatapart_4d(cols, dffields, numrows, datasb) + elseif plottype == :multiline || plottype == :trumpet #3D with 2 indices, one of which is time + cols = (df[!, 1], df[!, 2], df[!, 3]) + datastring = getdatapart_3d_time(cols, dffields, numrows, datasb) + elseif plottype == :multihistogram || plottype == :multibar || plottype == :multiscatter #3D with 2 indices, none of which is time + cols = (df[!, 1], df[!, 2], df[!, 3]) + datastring = getdatapart_3d(cols, dffields, numrows, datasb) + elseif plottype == :line #2D with 1 index, one of which is time + cols = (df[!, 1], df[!, 2]) + datastring = getdatapart_2d_time(cols, dffields, numrows, datasb) + else # :bar and :histogram + cols = (df[!, 1], df[!, 2]) + datastring = getdatapart_2d(cols, dffields, numrows, datasb) + end + + append!(sb, datastring * "]"); + datapart = String(sb) + + return JSON.JSONText(datapart) +end + +function getdatapart_4d(cols, dffields, numrows, datasb) + for i = 1:numrows + + append!(datasb, "{ + \"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) * "\", + \"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\", + \"" * dffields[3] * "\":\"" * string(cols[3][i]) * "\", + \"" * dffields[4] * "\":\"" * string(cols[4][i]) * "\"}") + + if i != numrows + append!(datasb, ",") + end + end + return String(datasb) +end + +function getdatapart_3d_time(cols, dffields, numrows, datasb) + for i = 1:numrows + + append!(datasb, "{\"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) + * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\",\"" + * dffields[3] * "\":\"" * string(cols[3][i]) * "\"}") + + if i != numrows + append!(datasb, ",") + end + end + return String(datasb) +end + +function getdatapart_3d(cols, dffields, numrows, datasb) + for i = 1:numrows + + append!(datasb, "{\"" * dffields[1] * "\":\"" * string(cols[1][i]) + * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\",\"" + * dffields[3] * "\":\"" * string(cols[3][i]) * "\"}") + + if i != numrows + append!(datasb, ",") + end + end + return String(datasb) +end + +function getdatapart_2d_time(cols, dffields, numrows, datasb) + for i = 1:numrows + append!(datasb, "{\"" * dffields[1] * "\":\"" * string(Date(cols[1][i])) + * "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\"}") + + if i != numrows + append!(datasb, ",") + end + end + + return String(datasb) +end + +function getdatapart_2d(cols, dffields, numrows, datasb) + for i = 1:numrows + + append!(datasb, "{\"" * dffields[1] * "\":\"" * string(cols[1][i]) * + "\",\"" * dffields[2] * "\":\"" * string(cols[2][i]) * "\"}") #end of dictionary + + if i != numrows + append!(datasb, ",") + end + end + return String(datasb) +end diff --git a/test/test_explorer_model.jl b/test/test_explorer_model.jl index 3ab0d466b..046302097 100644 --- a/test/test_explorer_model.jl +++ b/test/test_explorer_model.jl @@ -149,3 +149,42 @@ set_leftover_params!(m, Dict{String, Any}([ run(m) w = explore(m) close(w) + +# 8. More plot types + +@defcomp example begin + p0 = Parameter(index = [time]) # line plot + p1 = Parameter(index = [foo]) # scatter plot + p2 = Parameter(index = [baz]) # bar plot + + p3 = Parameter(index = [foo, bar]) # multi-scatter + p4 = Parameter(index = [baz, foo]) # multi-bar + p5 = Parameter(index = [time, bar]) # multi-line + p6 = Parameter(index = [time, baz]) # multi-line + + x = Variable(index = [time]) + function run_timestep(p,v,d,t) + v.x[t] = 0 + end +end + +m = Model() + +set_dimension!(m, :time, 2000:2009) +set_dimension!(m, :foo, 1:5) +set_dimension!(m, :bar, 1:3) +set_dimension!(m, :baz, [:A, :B, :C]) + +add_comp!(m, example) + +set_param!(m, :example, :p0, 1:10) +set_param!(m, :example, :p1, 6:10) +set_param!(m, :example, :p2, 4:6) + +set_param!(m, :example, :p3, reshape(1:15, 5, 3)) +set_param!(m, :example, :p4, reshape(1:15, 3, 5)) +set_param!(m, :example, :p5, reshape(1:30, 10, 3)) +set_param!(m, :example, :p6, reshape(1:30, 10, 3)) + +run(m) +explore(m) diff --git a/wip/temp.jl b/wip/temp.jl deleted file mode 100644 index 144b9e6a4..000000000 --- a/wip/temp.jl +++ /dev/null @@ -1,33 +0,0 @@ -using Mimi - -@defcomp example begin - p0 = Parameter(index = [time]) - p1 = Parameter(index = [foo]) - p2 = Parameter(index = [foo, bar]) - p3 = Parameter(index = [foo, baz]) - p4 = Parameter(index = [time, bar]) - p5 = Parameter(index = [time, baz]) - - x = Variable(index = [time]) - function run_timestep(p,v,d,t) - v.x[t] = 0 - end -end - -m = Model() - -set_dimension!(m, :time, collect(1:10)) -set_dimension!(m, :foo, 1:5) -set_dimension!(m, :bar, 1:3) -set_dimension!(m, :baz, [:A, :B, :C]) - -add_comp!(m, example) - -set_param!(m, :example, :p0, 1:10) -set_param!(m, :example, :p1, 1:5) -set_param!(m, :example, :p2, reshape(1:15, 5, 3)) -set_param!(m, :example, :p3, reshape(1:15, 5, 3)) -set_param!(m, :example, :p4, reshape(1:30, 10, 3)) -set_param!(m, :example, :p5, reshape(1:30, 10, 3)) -run(m) -explore(m) \ No newline at end of file From 80392ed59cdfa0fdc85a5dc8751a8138db901957 Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 17:45:49 -0700 Subject: [PATCH 4/6] Add tests --- test/test_explorer_model.jl | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/test/test_explorer_model.jl b/test/test_explorer_model.jl index 046302097..bbf54aae2 100644 --- a/test/test_explorer_model.jl +++ b/test/test_explorer_model.jl @@ -13,13 +13,23 @@ function _is_VegaLite_v3() end @defcomp MyComp begin - a = Parameter(index=[time, regions]) - b = Parameter(index=[time]) - c = Parameter(index=[regions]) + a = Parameter(index=[time, regions]) # multiline + b = Parameter(index=[time]) # line + c = Parameter(index=[regions]) # bar d = Parameter() e = Parameter(index=[four]) f = Parameter{Array{Float64, 2}}() + g = Paramter(index = [subregions]) + p0 = Parameter(index = [time]) # line plot + p1 = Parameter(index = [foo]) # scatter plot + p2 = Parameter(index = [baz]) # bar plot + + p3 = Parameter(index = [foo, bar]) # multi-scatter + p4 = Parameter(index = [baz, foo]) # multi-bar + p5 = Parameter(index = [time, bar]) # multi-line + p6 = Parameter(index = [time, baz]) # multi-line + x = Variable(index=[time, regions]) function run_timestep(p, v, d, t) @@ -156,7 +166,6 @@ close(w) p0 = Parameter(index = [time]) # line plot p1 = Parameter(index = [foo]) # scatter plot p2 = Parameter(index = [baz]) # bar plot - p3 = Parameter(index = [foo, bar]) # multi-scatter p4 = Parameter(index = [baz, foo]) # multi-bar p5 = Parameter(index = [time, bar]) # multi-line @@ -188,3 +197,15 @@ set_param!(m, :example, :p6, reshape(1:30, 10, 3)) run(m) explore(m) + +items = [:p0, :p1, :p2, :p3, :p4, :p5, :p6] +for item in items + static_spec = _spec_for_item(m, :example, item; interactive = false) + interactive_spec = _spec_for_item(m, :example, item) + if length(dim_names(m, :example, item)) == 0 + name = string(:example, " : ", item, " = ", m[:example, item]) + else + name = string(:example, " : ", item) + end + @test static_spec["name"] == interactive_spec["name"] == name +end From 9e40e8180b5d952efbd8cfae8166990f9738d16b Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 19:56:47 -0700 Subject: [PATCH 5/6] Fix typo --- test/test_explorer_model.jl | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/test_explorer_model.jl b/test/test_explorer_model.jl index bbf54aae2..5cb1a169d 100644 --- a/test/test_explorer_model.jl +++ b/test/test_explorer_model.jl @@ -19,16 +19,7 @@ end d = Parameter() e = Parameter(index=[four]) f = Parameter{Array{Float64, 2}}() - - g = Paramter(index = [subregions]) - p0 = Parameter(index = [time]) # line plot - p1 = Parameter(index = [foo]) # scatter plot - p2 = Parameter(index = [baz]) # bar plot - - p3 = Parameter(index = [foo, bar]) # multi-scatter - p4 = Parameter(index = [baz, foo]) # multi-bar - p5 = Parameter(index = [time, bar]) # multi-line - p6 = Parameter(index = [time, baz]) # multi-line + g = Parameter(index = [subregions]) x = Variable(index=[time, regions]) From fdf6bf91abede100097c9df7dfb74db3ea4668ca Mon Sep 17 00:00:00 2001 From: lrennels Date: Tue, 16 Mar 2021 20:13:08 -0700 Subject: [PATCH 6/6] Fix bug --- test/test_explorer_model.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/test_explorer_model.jl b/test/test_explorer_model.jl index 5cb1a169d..c40015ec4 100644 --- a/test/test_explorer_model.jl +++ b/test/test_explorer_model.jl @@ -13,13 +13,12 @@ function _is_VegaLite_v3() end @defcomp MyComp begin - a = Parameter(index=[time, regions]) # multiline - b = Parameter(index=[time]) # line - c = Parameter(index=[regions]) # bar + a = Parameter(index=[time, regions]) + b = Parameter(index=[time]) + c = Parameter(index=[regions]) d = Parameter() e = Parameter(index=[four]) f = Parameter{Array{Float64, 2}}() - g = Parameter(index = [subregions]) x = Variable(index=[time, regions])