[1]:
import emat
emat.versions()
emat 0.5.2, plotly 4.14.3

Interactive Explorer

TMIP-EMAT includes an interactive visualizer, inspired by a similar tool provided with the VisionEval package. To demonstrate the interactive visualizer, we will use the Road Test example model. First, we need to develop and run a design of experiments to have some data to explore. We’ll run 5,000 experiments to get a good size sample of data points to visualize.

[3]:
import emat.examples
scope, db, model = emat.examples.road_test()
design = model.design_experiments(n_samples=5000)
results = model.run_experiments(design)

One feature of the visualizer is the ability to display not only a number of results, but also to contrast those results against a given “reference” model that represents a more traditional single-point forecast of inputs and results. We’ll prepare a reference point here using the run_reference_experiment method of the CoreModel class, which reads the input parameter defaults (as defined in the scope), and returns both inputs and outputs in a DataFrame (essentially, an experimental design with only a single experiment), suitable for use as the reference point marker in our visualizations.

[4]:
refpoint = model.run_reference_experiment()

The interactive visualizer class can be imported from the emat.analysis package. To use it, we create an Visualizer instance, giving a scope and a set of experimental results, as well as the reference point.

[5]:
from emat.analysis import Visualizer
/Users/jeffnewman/LocalGit/tmip-emat/emat/workbench/analysis/prim.py:30: ImportWarning:

altair based interactive inspection not available

[6]:
viz = Visualizer(scope=scope, data=results, reference_point=refpoint)

Single Dimension Figures

To build a complete interactive workspace similar to that provided by VisionEval, we can use the complete method of the Visualizer instance we created above. This will create a set of histograms illustrating the data in the results computed above. There is one histogram for each policy lever, exogenous uncertainty, and performance measure.

A range of data in each histogram can be selected by dragging horizonatally across the figure. For continuous parameters (i.e. float or integer valued parameters) you can select a single contiguous range by dragging across that range, and deselect by double clicking on the figure (or by selecting the entire possible range). For discrete parameters (i.e. boolean or categorical parameters, identifiable by the larger gaps between the bars in the figure) dragging across the center of any bar toggles whether that bar is selected or not. This allows non-contiguous selections in categories that have 3 or more possible values. Like the other figures, any selection can be cleared by double-clicking.

Selections can be made simultaneously over any combination of uncertainties, policy levers, and performance measures. The combination of controls offered can be used interactively to select and highlight only a subset of the experiments in the complete data set. By manipulating these controls, users can explore the interaction across various inputs and outputs.

Selecting from histograms
[7]:
viz.complete()

It is also possible to display just a small subset of the figures of this interactive viewer. This could be convenient, for example, if there are a very large number of performance measures.

[8]:
viz.selectors(['input_flow', 'expand_capacity', 'net_benefits'])

In addition to manipulating the controls interactively, they can also be set programatically from Python code. To do so, we can define a new emat.Box that declares lower and/or upper bounds for any continuous dimensions, as well as the set of allowed (included) value for any discrete dimensions, and then add that new box to this visualizer using the Visualizer.add_box() command.

[9]:
box = emat.Box("Passable", scope=scope)
box.set_upper_bound('cost_of_capacity_expansion', 400)
box.set_lower_bound('time_savings', 5)
box.remove_from_allowed_set('debt_type', 'GO Bond')
viz.add_box(box)

Alternatively, a new box can be created and added to the Visualier with a single :meth:Visualizer.new_box command, which passes most keyword arguments through to the :class:emat.Box constuctor.

[10]:
viz.new_box('Profitable', lower_bounds={'net_benefits':0});

Each of these new boxes is added to the Visualizer seperately. You can switch between different active boxes using the dropdown selector at the top of the complete interface – this same selector is available within the smaller status widget:

[11]:
viz.status()

You can also programatically find and change the active box from Python:

[12]:
viz.active_selection_name()
[12]:
'Profitable'
[13]:
viz.set_active_selection_name("Passable")
viz.active_selection_name()
[13]:
'Passable'

When interactively changing bounds by dragging on figures, the currently “active” box is modified with the revised bounds. The entire set of bounds can be cleared at once with the clear_box method, which by default clears the settings on the active box selection; give a name to clear the settings from a different box selection.

[14]:
viz.clear_box()

If instead we want to manipulate an existing box selection, we can access the Box object, manipulate it (e.g. by using remove_from_allowed_set or add_to_allowed_set), and write it back into the Visualizer.

[15]:
box = viz['Profitable']
box.remove_from_allowed_set('debt_type', 'Rev Bond')
viz['Profitable'] = box

Two Dimension Figures

The Visualizer object can also create an interactive two-dimensional scatter plot, using the two_way method. This method allows the user to specify the variables for both the x and y axis, and either can be any policy lever, exogenous uncertainty, or performance measure. These dimensions can be changed interactively later as well. The resulting scatter plot is linked to the same selection of experiments in the interactive one-dimensional figures shown above, and by default the same experiments are highlighted in the same color scheme in all of these related figures.

[16]:
viz.two_way(x='expand_capacity', y='time_savings')

One useful feature of the two_way is the ability to manually “lasso” a selection of data points. This lasso selection does not need to be anything like a rectangular box selection, as we have seen so far. Once a lasso selection of data points is made in the figure above, you can choose “Use Manual Selection” from the Edit Selection... menu at right, which will create a new Visualizer selection from the selected data. The highlight color changes to signify that this is not an editable rectangular box, and the selected data will be highlighted in all figures linked to this Visualizer, including the histograms above.

In addition to the two_way, which offers a feature-packed view of two dimensions at a time, there is also a scatter plot matrix Visualizer.splom() option, which displays a configurable matrix of similar two dimensional views.

[17]:
viz.splom(
    rows=('expand_capacity','time_savings','net_benefits'),
    cols='L',
    reset=True
)
[18]:
viz.hmm(
    rows=('time_savings','net_benefits'),
    cols='L',
    show_points=100,
    reset=True,
)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-18-af81d9f65bf5> in <module>
----> 1 viz.hmm(
      2     rows=('time_savings','net_benefits'),
      3     cols='L',
      4     show_points=100,
      5     reset=True,

~/LocalGit/tmip-emat/emat/analysis/explore_2/explore_visualizer.py in hmm(self, key, reset, cols, rows, emph_selected, show_points, size, with_hover)
   1029                         box = self._selection_defs[name].to_emat_box()
   1030
-> 1031                 self._hmm[key] = new_hmm_figure(
   1032                         self.scope,
   1033                         self.data,

~/LocalGit/tmip-emat/emat/analysis/explore_2/components/__init__.py in new_hmm_figure(scope, data, rows, cols, row_titles, size, selection, box, refpoint, figure_class, on_select, on_deselect, selected_color, unselected_color, emph_selected, show_points, show_points_frac, marker_size, with_hover)
   1506                 with_hover=True,
   1507 ):
-> 1508         import datashader as ds  # optional dependency
   1509
   1510         if unselected_color is None:

ModuleNotFoundError: No module named 'datashader'
[ ]:
viz.new_selection(
    "time_savings * input_flow > 1000 & cost_of_capacity_expansion < 300",
    name="TimeSaved"
)

Dynamic Feature Scoring

EMAT can score the relative importance of inputs for an experiment being within the selection, either for a typical rectangular selection based on thresholds, or for any arbitrary selection. These scores are recomputed and updated in near-real-time as the thresholds are adjusted.

When the selection includes rectangular thresholds set on both inputs and outputs, the thresholded inputs are automatically excluded from the scoring algorithm.

[ ]:
viz.selection_feature_scores()

Using PRIM with the Interactive Explorer

The PRIM tools are available directly within the interactive explorer. Simply set a target as shown.

[20]:
prim = viz.prim(target="net_benefits >= 0")
[21]:
box1 = prim.find_box()

The tradeoff selector is directly integrated into the explorer. In addition to the information visible by hovering over any point in the tradeoff selector figure, clicking on that point will create a new selection in the explorer, and set all of the interactive constraints to the bounds given by that particular point.

[22]:
box1.tradeoff_selector()
[23]:
box1.select(20)
[24]:
viz.status()
[25]:
viz.lever_selectors()

We can also use PRIM to explore solutions based only on manipulating the policy levers, and not the combination of all inputs (levers & uncertainties).

[26]:
prim_levers = viz.prim('levers', target="Profitable")
[27]:
prim_levers.tradeoff_selector()
[28]:
viz.parcoords()