Visualization

Warning

The visualization library is still in active development and we hope to improve on it in future releases. Please use its functionality at your own discretion.

The IDAES visualization module is built on top of bokeh and is meant to support multiple plot types. The data for these plots is input through dataframes defined via data-frame schemas.

The Plot class

The plot class implements different IDAES plots. Each of its methods acts like a factory method returning an instance of the Plot that can then be modified by calls to helper methods (e.g: saving a plot to disk). Currently only heat exchanger network diagrams are supported.

class idaes.vis.plot.Plot(current_plot=None)[source]
annotate(x, y, label)[source]

Annotate a plot with a given point and a label.

Parameters:
  • x – Value of independent variable.
  • y – Value of dependent variable.
  • label – Text label.
Returns:

None

Raises:

None

classmethod goodness_of_fit(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Draw y against predicted value (y^) and display (calculate?) value of R^2.

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • x – Key in data-frame to use as x-axis.
  • y – Keys in data-frame to plot on y-axis.
  • title – Title for a plot.
  • xlab – Label for x-axis.
  • ylab – Label for y-axis.
  • y_axis_type – Specify “log” to pass logarithmic scale.
  • legend – List of strings matching y.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.
classmethod heat_exchanger_network(exchangers, stream_list, mark_temperatures_with_tooltips=False, mark_modules_with_tooltips=False, stage_width=2, y_stream_step=1)[source]

Plot a heat exchanger network diagram.

Parameters:
  • exchangers

    List of exchangers where each exchanger is a dict of the form:

    {'hot': 'H2', 'cold': 'C1', 'Q': 1400, 'A': 159, 'annual_cost': 28358,
    'stg': 2}
    

    where hot is the hot stream name, cold is the cold stream name, A is the area (in m^2), annual_cost is the annual cost in $, Q is the amount of heat transferred from one stream to another in a given exchanger and stg is the stage the exchanger belongs to. The utility_type, if present, will specify if we plot the cold stream as water (idaes.vis.plot_utils.HENStreamType.cold_utility) or the hot stream as steam (idaes.vis.plot_utils.HENStreamType.hot_utility).

    Additionally, the exchanger could have the key modules, like this:

    {'hot': 'H1', 'cold': 'C1', 'Q': 667, 'A': 50, 'annual_cost': 10979, 'stg': 3,
    'modules': {10: 1, 20: 2}}
    

    The value of this key is a dictionary where each key is a module area and each value is how many modules of that area are in the exchanger. It’s indicated as a tooltip on the resulting diagram.

    If a stream is involved in multiple exchanges in teh same stage, the stream will split into multiple sub-streams with each sub-stream carrying one of the exchanges.

  • stream_list

    List of dicts representing streams where each item is a dict of the form:

    {'name':'H1', 'temps': [443, 435, 355, 333], 'type': HENStreamType.hot}
    
  • mark_temperatures_with_tooltips – if True, we plot the stream temperatures and assign hover tooltips to them. Otherwise, we label them with text labels.
  • mark_modules_with_tooltips – if True, we plot markers for modules (if present) and assign hover tooltips to them. Otherwise, we don’t add module info.
  • stage_width – How many units to use for each stage in the diagram (defaults to 2).
  • y_stream_step – How many units to use to separate each stream/sub-stream from the next (defaults to 1).
classmethod isobar(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Need more information.

classmethod profile(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

A profile plot includes 2 dependent variables and a single independent variable. Based on the Jupyter notebook here.

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • x – Key in data-frame to use as x-axis.
  • y – Keys in data-frame to use as y-axis.
  • title – Title for a plot.
  • xlab – Label for x-axis.
  • ylab – Label for y-axis.
  • y_axis_type – Specify “log” to pass logarithmic scale.
  • legend – List of strings matching y.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.
classmethod property_model(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Draw pressure/enthalpy plots for different levels of temperature.

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • x – Key in data-frame to plot on x-axis.
  • y – Keys in data-frame to plot on y-axis.
  • title – Title for a plot.
  • xlab – Label for x-axis.
  • ylab – Label for y-axis.
  • y_axis_type – Specify “log” to pass logarithmic scale.
  • legend – List of strings matching y.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.
classmethod residual(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Plot x, some continuous value (e.g: T, P), against Y (% residual value). Is this %-value calculated from variables in the idaes_model_object?

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • x – Key in data-frame to use as x-axis.
  • y – Keys in data-frame to plot on y-axis.
  • title – Title for a plot.
  • xlab – Label for x-axis.
  • ylab – Label for y-axis.
  • y_axis_type – Specify “log” to pass logarithmic scale.
  • legend – List of strings matching y.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.
resize(height=-1, width=-1)[source]

Resize a plot’s height and width.

Parameters:
  • height – Height in screen units.
  • width – Width in screen units.
Returns:

None

Raises:

None

save(destination)[source]

Save the current plot object to HTML in filepath provided by destination.

Parameters:destination – Valid file path to save HTML to.
Returns:filename where HTML is saved.
Raises:None
classmethod sensitivity(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Need more information.

show(in_notebook=True)[source]

Display plot in a Jupyter notebook.

Parameters:
  • self – Plot object.
  • in_notebook – Display in Jupyter notebook or generate HTML file.
Returns:

None

Raises:

None

classmethod stream_table(data_frame, title='')[source]

Display a table for all names in the idaes_model_object_names indexing rows according to row_start and row_stop.

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • title – Title for a plot.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.
classmethod tradeoff(data_frame, x='', y=[], title='', xlab='', ylab='', y_axis_type='auto', legend=[])[source]

Draw some parameter varying and the result on the objective value.

Parameters:
  • data_frame – a data frame with keys contained in x and y.
  • x – Key in data-frame to use as x-axis.
  • y – Keys in data-frame to plot on y-axis.
  • title – Title for a plot.
  • xlab – Label for x-axis.
  • ylab – Label for y-axis.
  • y_axis_type – Specify “log” to pass logarithmic scale.
  • legend – List of strings matching y.
Returns:

Plot object on success.

Raises:
  • MissingVariablesException – Dependent variable or their data not passed.
  • BadDataFrameException – No data-frame was generated for the model object.

Plot utilities

The plot utilities module implements helper/utility methods used for visualization.

class idaes.vis.plot_utils.HENStreamType[source]

Enum type defining hot and cold streams

idaes.vis.plot_utils.add_exchanger_labels(plot, x, y_start, y_end, label_font_size, exchanger, module_marker_line_color, module_marker_fill_color, mark_modules_with_tooltips)[source]

Plot exchanger labels for an exchanger (for Q and A) on a heat exchanger network diagram and add module markers (if needed).

Parameters:
  • plot – bokeh.plotting.plotting.figure instance.
  • label_font_size – font-size for labels.
  • x – x-axis coordinate of exchanger (exchangers are vertical lines so we just need 1 x-value)
  • y_start – y-axis coordinate of exchanger start.
  • y_end – y-axis coordinate of exchanger end.
  • exchanger

    exchanger dictionary of the form:

    {'hot': 'H2', 'cold': 'C1', 'Q': 1400, 'A': 159, 'annual_cost': 28358,
     'stg': 2}
    
  • module_marker_line_color – color of border of the module marker.
  • module_marker_fill_color – color inside the module marker.
  • mark_modules_with_tooltips – whether to add tooltips to plot or not (currently not utilized).
Returns:

modified bokeh.plotting.plotting.figure instance with labels added.

Raises:

None

idaes.vis.plot_utils.add_module_markers_to_heat_exchanger_plot(plot, x, y, modules, line_color, fill_color, mark_modules_with_tooltips)[source]

Plot module markers as tooltips to a heat exchanger network diagram.

Parameters:
  • plot – bokeh.plotting.plotting.figure instance.
  • x – x-axis coordinate of module marker tooltip.
  • y – y-axis coordinate of module marker tooltip.
  • modules – dict containing modules.
  • line_color – color of border of the module marker.
  • fill_color – color inside the module marker.
  • mark_modules_with_tooltips – whether to add tooltips to plot or not (currently not utilized).
Returns:

bokeh.plotting.plotting.figure instance with module markers added.

Raises:

None

idaes.vis.plot_utils.get_color_dictionary(set_to_color)[source]

Given a set, return a dictionary of the form:

{'set_member': valid_bokeh_color}
Args:
set_to_color: set of unique elements, e.g: [1,2,3] or [“1”, “2”, “3”]
Returns:

Dictionary of the form:

{'set_member': valid_bokeh_color}
Raises:
None
idaes.vis.plot_utils.get_stream_y_values(exchangers, hot_streams, cold_streams, y_stream_step=1)[source]

Return a dict containing the layout of the heat exchanger diagram including any stage splits.

Parameters:
  • exchangers

    List of exchangers where each exchanger is a dict of the form:

    {'hot': 'H2', 'cold': 'C1', 'Q': 1400, 'A': 159, 'annual_cost': 28358,
    'stg': 2}
    

    where hot is the hot stream name, cold is the cold stream name, A is the area (in m^2), annual_cost is the annual cost in $, Q is the amount of heat transferred from one stream to another in a given exchanger and stg is the stage the exchanger belongs to. Additionally a ‘utility_type’ can specify if we draw the cold stream as water (idaes.vis.plot_utils.HENStreamType.cold_utility) or the hot stream as steam (idaes.vis.plot_utils.HENStreamType.hot_utility).

    Additionally, the exchanger could have the key ‘modules’, like this:

    {'hot': 'H1', 'cold': 'C1', 'Q': 667, 'A': 50, 'annual_cost': 10979, 'stg': 3,
    'modules': {10: 1, 20: 2}}
    
  • hot_streams

    List of dicts representing hot streams where each item is a dict of the form:

    {'name':'H1', 'temps': [443, 435, 355, 333], 'type': HENStreamType.hot}
    
  • cold_streams

    List of dicts representing cold streams where each item is a dict of the form:

    {'name':'H1', 'temps': [443, 435, 355, 333], 'type': HENStreamType.hot}
    
  • y_stream_step – how many units on the HEN diagram to leave between each stream (or sub-stream) and the one above it. Defaults to 1.
Returns:

* stream_y_values_dict : a dict of each stream name as key and value being a dict of the form

This indicates what the default y value of this stream will be on the diagram and what values we’ll use when it splits.

* hot_split_streams : list of tuples of the form (a,b) where a is a hot stream name and b is the max. times it will split over all the stages.

* cold_split_streams : list of tuples of the form (a,b) where a is a cold stream name and b is the max. times it will split over all the stages.

Return type:

Tuple containing 3 dictionaries to be used when plotting the HEN

Raises:

None

idaes.vis.plot_utils.is_hot_or_cold_utility(exchanger)[source]

Return if an exchanger is a hot or a cold utility by checking if it has the key utility_type.

Parameters:exchanger – dict representing the exchanger.
Returns:True if utility_type in the exchanger dict passed.
Raises:None
idaes.vis.plot_utils.plot_line_segment(plot, x_start, x_end, y_start, y_end, color='white', legend=None)[source]

Plot a line segment on a bokeh figure.

Parameters:
  • plot – bokeh.plotting.plotting.figure instance.
  • x_start – x-axis coordinate of 1st point in line.
  • x_end – x-axis coordinate of 2nd point in line.
  • y_start – y-axis coordinate of 1st point in line.
  • y_end – y-axis coordinate of 2nd point in line.
  • color – color of line (defaults to white).
  • legend – what legend to associate with (defaults to None).
Returns:

modified bokeh.plotting.plotting.figure instance with line added.

Raises:

None

idaes.vis.plot_utils.plot_stream_arrow(plot, line_color, stream_arrow_temp, temp_label_font_size, x_start, x_end, y_start, y_end, stream_name=None)[source]

Plot a stream arrow for the heat exchanger network diagram.

Parameters:
  • plot – bokeh.plotting.plotting.figure instance.
  • line_color – color of arrow (defaults to white).
  • stream_arrow_temp – Tempreature of the stream to be plotted.
  • temp_label_font_size – font-size of the temperature label to be added.
  • x_start – x-axis coordinate of arrow base.
  • x_end – x-axis coordinate of arrow head.
  • y_start – y-axis coordinate of arrow base.
  • y_end – y-axis coordinate of arrow head.
  • stream_name – Name of the stream to add as a label to arrow (defaults to None).
Returns:

modified bokeh.plotting.plotting.figure instance with stream arrow added.

Raises:

None

idaes.vis.plot_utils.turn_off_grid_and_axes_ticks(plot)[source]

Turn off axis ticks and grid lines on a bokeh figure object.

Parameters:plot – bokeh.plotting.plotting.figure instance.
Returns:modified bokeh.plotting.plotting.figure instance.
Raises:None
idaes.vis.plot_utils.validate(data_frame, x, y, legend=None)[source]

Validate that the plot parameters are valid.

Parameters:
  • data_frame – a pandas data frame of any type.
  • x – Key in data-frame to use as x-axis.
  • y – Keys in data-frame to use as y-axis.
  • legend – List of labels to use as legend for a plot.
Returns:

True on valid data frames (if x and y are in the data frame keys) Raises exceptions otherwise.

Raises:
  • MissingVariablesException - on bad legend labels (if passed)
  • BadDataFrameException - on invalid data frame.

Examples

Drawing heat exchanger network diagrams

The following example demonstrates how to generate a heat exchanger network diagram.

In the code below, different streams are defined in the streams list. For each stream, we expect a name (name), a list of temperatures (temps) and a type field specifying if this is a hot stream (HENStreamType.hot) or a cold one (HENStreamType.cold).

The exchangers list defines the heat exchangers. Each exchanger is defined by its hot/cold stream (hot, cold) which must match one of the streams in the streams list above. We also require for each exchanger the area (A),the amount of heat transferred from one stream to another (Q), annual cost (annual_cost) and stage (stg). If the utility_type key is passed and it’s set to HENStreamType.cold_utility then we draw the cold stream of the exchanger as water. If the utility_type key is passed and it’s set to HENStreamType.hot_utility then we draw the hot stream of the exchanger as steam.

The color-codes of each stage are picked randomly in the final diagram.

from bokeh.io import output_notebook
from bokeh.plotting import show
from idaes.vis.plot import Plot
from idaes.vis.plot_utils import HENStreamType

exchangers = [
    {'hot': 'H2', 'cold': 'C1', 'Q': 1400, 'A': 159, 'annual_cost': 28358, 'stg': 2},
    {'hot': 'H1', 'cold': 'C1', 'Q': 667, 'A': 50, 'annual_cost': 10979, 'stg': 3},
    {'hot': 'H1', 'cold': 'C1', 'Q': 233, 'A': 10, 'annual_cost': 4180, 'stg': 1},
    {'hot': 'H1', 'cold': 'C2', 'Q': 2400, 'A': 355, 'annual_cost': 35727, 'stg': 2},
    {'hot': 'H2', 'cold': 'W', 'Q': 400, 'A': 50, 'annual_cost': 10979, 'stg': 3, 'utility_type': HENStreamType.cold_utility},
    {'hot': 'S', 'cold': 'C2', 'Q': 450, 'A': 50, 'annual_cost': 0, 'stg': 1, 'utility_type': HENStreamType.hot_utility}
]

streams = [
    {'name':'H2', 'temps': [423, 423, 330, 303], 'type': HENStreamType.hot},
    {'name':'H1', 'temps': [443, 435, 355, 333], 'type': HENStreamType.hot},
    {'name':'C1', 'temps': [408, 396, 326, 293], 'type': HENStreamType.cold},
    {'name':'C2', 'temps': [413, 413, 353, 353], 'type': HENStreamType.cold}
]
plot_obj = Plot.heat_exchanger_network(exchangers, streams,
    mark_temperatures_with_tooltips=True)
plot_obj.show()
Bokeh Application

By default tooltips are used to mark stream temperatures. We can disable those and add labels instead as seen below. They can be a bit crowded and for now you can just zoom in to decipher crowded labels (but we’re working on that!)

plot_obj = Plot.heat_exchanger_network(exchangers, streams,
    mark_temperatures_with_tooltips=False)
plot_obj.show()
Bokeh Application

In case a stream exchanges with multiple streams in the same stage, this is handled through a stage split. We also currently support describing modules for each exchanger that are added as tooltips to the area label on each exchanger. The example below demonstrates this functionality:

exchangers = [
    {'hot': 'H1', 'cold': 'C2', 'Q': 2400, 'A': 355, 'annual_cost': 35727, 'stg': 2},
    {'hot': 'H2', 'cold': 'C2', 'Q': 1700, 'A': 159, 'annual_cost': 28358, 'stg': 2},


    {'hot': 'H1', 'cold': 'C2', 'Q': 1700, 'A': 159, 'annual_cost': 28358, 'stg': 3},
    {'hot': 'H1', 'cold': 'C1', 'Q': 667, 'A': 50, 'annual_cost': 10979, 'stg': 3, 'modules': {10: 1, 20: 2}},
    {'hot': 'H2', 'cold': 'C3', 'Q': 1700, 'A': 159, 'annual_cost': 28358, 'stg': 3},
    {'hot': 'H2', 'cold': 'C2', 'Q': 1700, 'A': 159, 'annual_cost': 28358, 'stg': 3, 'modules': {10: 1, 20: 2}},
    {'hot': 'H3', 'cold': 'C2', 'Q': 1700, 'A': 159, 'annual_cost': 28358, 'stg': 3},

    {'hot': 'H2', 'cold': 'W', 'Q': 400, 'A': 50, 'annual_cost': 10979, 'stg': 3, 'utility_type': HENStreamType.cold_utility},
    {'hot': 'S', 'cold': 'C2', 'Q': 450, 'A': 50, 'annual_cost': 0, 'stg': 1, 'utility_type': HENStreamType.hot_utility}
]

streams = [
    {'name':'H3', 'temps': [423, 423, 330, 303], 'type': HENStreamType.hot},
    {'name':'H2', 'temps': [423, 423, 330, 303], 'type': HENStreamType.hot},
    {'name':'H1', 'temps': [443, 435, 355, 333], 'type': HENStreamType.hot},
    {'name':'C1', 'temps': [408, 396, 326, 293], 'type': HENStreamType.cold},
    {'name':'C2', 'temps': [413, 413, 353, 353], 'type': HENStreamType.cold},
    {'name':'C3', 'temps': [413, 413, 353, 353], 'type': HENStreamType.cold}
]
plot_obj = Plot.heat_exchanger_network(exchangers, streams,
    mark_temperatures_with_tooltips=True,
    mark_modules_with_tooltips=True,
    stage_width=2,
    y_stream_step=1)
plot_obj.show()
Bokeh Application

Plotting profile plots from the MEA example

Note: The following has not been tested recently and should be considered a work in progress.

The following examples demonstrate the resize, annotation and saving functionalities.

In the following example, we being by preparing a data frame from our flowsheet variables.

# Absorber CO2 Levels
from pandas import DataFrame
import os
tmp = fs.absorb.make_profile(t=0)
tmp = fs.regen.make_profile(t=0)

plot_dict = {'z':fs.absorb.profile_1['z'],
             'y1':fs.absorb.profile_1.y_vap_CO2*101325.0,
             'y2':fs.absorb.profile_1.P_star_CO2}
plot_data_frame = DataFrame(data=plot_dict)

We can then plot the data frame we just made, show it, resize it and save it.

absorber_co2_plot = Plot.profile(plot_data_frame,
                                 x = 'z',
                                 y = ['y1','y2'],
                                 title = 'Absorber CO2 Levels',
                                 xlab = 'Axial distance from top (m)',
                                 ylab = 'Partial Pressure CO2 (Pa)',
                                 legend = ['Bulk vapor','Equilibrium'])

absorber_co2_plot.show()
absorber_co2_plot.save('/home/jovyan/model_contrib/absorber_co2_plot.html')
assert(os.path.isfile('/home/jovyan/model_contrib/absorber_co2_plot.html'))
Bokeh Application
absorber_co2_plot.resize(height=400,width=600)
absorber_co2_plot.show()
absorber_co2_plot.save('/home/jovyan/model_contrib/absorber_co2_plot_resized.html')
assert(os.path.isfile('/home/jovyan/model_contrib/absorber_co2_plot_resized.html'))
Bokeh Application

The following demonstrates the annotate functionality by plotting a second plot from the same flowsheet.

from IPython.core.display import display,HTML
stripper_co2_plot = Plot.profile(plot_data_frame,
                                 x = 'z',
                                 y = ['y1','y2'],
                                 title = 'Stripper CO2 Levels',
                                 xlab = 'Axial distance from top (m)',
                                 ylab = 'Partial Pressure CO2 (Pa)',
                                 legend = ['Bulk vapor','Equilibrium'])
stripper_co2_plot.show()
stripper_co2_plot.save('/home/jovyan/model_contrib/stripper_co2_plot.html')
assert(os.path.isfile('/home/jovyan/model_contrib/stripper_co2_plot.html'))
Bokeh Application

We can then annotate the “Reboiler vapor” point as shown below:

stripper_co2_plot.annotate(rloc,rco2p,'Reboiler vapor')
stripper_co2_plot.show()
stripper_co2_plot.save('/home/jovyan/model_contrib/stripper_co2_plot_annotated.html')
Bokeh Application