Open rolyp opened 3 weeks ago
Current proposal is to construct this functionality in two main stages:
grid
field for FigSpec
's
grid :: Array (Bind (Array Val))
or more likely grid :: Array (Bind (Array (Expr a)))
, to identify the sets of variables we wish to range over when constructing a faceted visualizationloadFig
to evaluate the combinations of parameter values all at once.fld
file is evaluated. This will eventually have to be revisited (see below and TODO: issue for backquote and synthesizing code fragments)TabularView
interface, which takes Array View
or Array2 View
(maybe just Array View
, defer the number of dimensions til later, it's entirely possible we'd need to generalize it to higher dimensions if you're faceting over 3 or more variables).TabularView
start off in 2-d grid formTabularView
's, most likely just listElement
composed with the appropriate selector for a given member of a TabularView
div
which has tabs at the top, with each tab comprising of a combination of parameter values@JosephBond Wondering if we need to modify loadfig
, or whether we can think of this as an internal detail of a new kind of View
(e.g. FacetView
). Maybe you could construct a FacetView
by supplying:
grid
as a Fluid value of type List
(or perhaps Dict
, if we want keys)View
Note: Re-evaluating fluid programs interactively dove-tails with the planned next steps of https://github.com/explorable-viz/fluid/issues/1040, since we need to examine how we do this. In my mind we will eventually want the backquote mechanism (and future synthesis of explanatory expressions) to be operate similarly to Faceting, (perhaps an interface like Github issues, with a preview tab showing the view you get from running the code.
@rolyp I think a dict makes more sense, with each faceted parameter being a key in the dict, then instead of setting variable names we could use the syntax for accessing dicts. Unfortunately, we have no special surface syntax for working with dicts.
For a contrived example, faceting a line-chart for a time series by a range of years, where get_points
is an accessor function that behaves as you'd expect, and the dict grid
binds the key "range"
to a list of possible ranges, we'd need something like:
LinePlot { name: "Example", data: get_points (nth choice (dict_get "range" grid)) }
In other words, it works but we'd probably want to add syntax for it at a later date. I'm still uncertain how we would then change the value of the variable choice
to match the user picking a different entry in the set of allowed ranges. Maybe I'm overcomplicating it, but it feels like even then we will need to spend time with the data-bindings, and use them to modify the values being returned to fluid, as well as the selections. Maybe it's not that difficult/I'm overcomplicating things though
Spitballing here (erring on the side of over-simplification rather than over-complication!), but perhaps FacetView
can be a list of {index, view}
records, where index
has some primitive type, and view
is an arbitrary view that may depend on index
. The renderer for FacetView
would provide custom UI for switching between different {index, view}
pairs, or perhaps arranging the various facets all in a column or table layout. The Fluid code for your example would be something like:
let series = [ … ]; // list of records with `year` field
years = [2015..2019] in
FacetView {
caption: “Example facet view”,
facets: [{
index: year,
view: LinePlot {
name: “Plot for “ ++ numToStr year,
data: [row | row <- series, row.year = year]
}
} | year <- years]
}
Here the “grid” isn’t explicit but rather just implicit in the various values of index
.
The naive repeated filtering here would be expensive, so some kind groupBy
or pivot
library function would help express this in an efficient way.
See also:
Thinking of FacetView
as simply another kind of View
would allow us to e.g. reimplement LineChart
as a FacetView
where each facet is a LinePlot
, with presentation options like:
LinePlot
rendered on the axes of the enclosing LineChart
LinePlot
s all superimposed on the axes provided by the enclosing LineChart
LinePlot
rendered into its own copy of the LineChart
, like a traditional facetingI think the question about interaction and what it might suggest in terms of more granular or demand-driven execution models is probably a distraction at this stage. Call-by-value programs in general do more work than strictly necessary, and this would just be another example of that – not fundamentally different from computing a list of 1,000 elements but only returning the first 10 elements to the user, or (as a more interactive example closer to the intuition you have in mind) presenting a view of the 1,000 records where only a window of 10 records is visible at any point in time (perhaps through a scrollable viewport).
A kind of composite plot which consists of a list of parameter values and for each value of the parameter, another kind of visualisation instantiated with that parameter value. For example, given a list of sources of methane emissions [Agriculture, Energy Sector, Forest Burning], a line chart plotting historical and projected methane emissions. The facet would support tabular layout of the individual subplots, but also a carousel-like interface which allows tabbing between a “current” subplot.
See also:
999
977
986