Tagging Classes

Tagging Classes#

IDAES contains classes for tagging model quantities and grouping them. The tags provide a convenient short cut to important model inputs and outputs and facilities for numeric formatting and displaying output in desired units.

Examples:#

The code below creates a simple model that can be used to demonstrate the use of tags.

import pyomo.environ as pyo
from idaes.core.util import ModelTag, ModelTagGroup

def model():
    m = pyo.ConcreteModel()
    m.w = pyo.Var([1, 2, 3], ["a", "b"], initialize=4, units=pyo.units.kg)
    m.x = pyo.Var([1, 2, 3], initialize=5, units=pyo.units.kg)
    m.y = pyo.Var(initialize=6, units=pyo.units.s)
    m.z = pyo.Var(initialize=7)
    m.e = pyo.Expression(expr=m.w[1, "a"] / m.x[1])
    m.f = pyo.Expression(expr=m.x[1] / m.y)

    @m.Expression([1, 2, 3], ["a", "b"])
    def g(b, i, j):
        return m.w[i, j] / m.x[i] * 100

    return m

The next code snippet creates a single tag object for the model variable w. While the structure of the example model is simple, IDAES models often have a complex structure, so tags provide a much shorter means to reference a quantity.

m = model()
tag = ModelTag(expr=m.w, format_string="{:.3f}", display_units=pyo.units.g)

Now we can use the tag to set model input and display model output.

# set all the elements of w with the second index of "a".
tag[:,"a"].set(2*pyo.units.kg)
tag[:,"b"].fix(3*pyo.units.kg)
assert str(tag[1, "a"]) == "2000.000 g"
assert str(tag[2, "a"]) == "2000.000 g"
assert str(tag[3, "a"]) == "2000.000 g"
assert str(tag[1, "b"]) == "3000.000 g"
assert str(tag[2, "b"]) == "3000.000 g"
assert str(tag[3, "b"]) == "3000.000 g"
assert tag[3, "b"].expression.fixed

# if no units are provided setting set_in_display_units to True will assume
# the display units. If it is False, the native units of the quantity will be
#used.
tag.set_in_display_units = True
tag[:,"a"].set(2)
assert str(tag[1, "a"]) == "2.000 g"
assert str(tag[2, "a"]) == "2.000 g"
assert str(tag[3, "a"]) == "2.000 g"

tag.str_include_units = False
assert str(tag[1, "a"]) == "2.000"

In addition to creating single tag objects, a tag group can be created. The ModelTagGroup class is a dictionary with added methods for dealing with groups of tags. When tags are in groups set_in_display_units and str_include_units are set for the group as a whole and cannot be set independently.

m = model()
group = ModelTagGroup()

group["w"] = ModelTag(expr=m.w, format_string="{:.3f}")
group["x"] = ModelTag(expr=m.x, format_string="{:.3f}", display_units=pyo.units.g)
group["y"] = ModelTag(expr=m.y, format_string="{:.3f}")
group["z"] = ModelTag(expr=m.z, format_string="{:.3f}")
group["e"] = ModelTag(expr=m.e, format_string="{:.3f}")
group["f"] = ModelTag(expr=m.f, format_string="{:.3f}")
group["g"] = ModelTag(expr=m.g, format_string="{:.3f}")

group.set_in_display_units = True
group.str_include_units = False

group["x"].set(2)
group["x"].setlb(1)
group["x"].setub(3)

assert str(group["x"][1]) == "2.000"
assert abs(group["x"][1].expression.lb - 0.001) < 1e-5 # x is in kg
assert abs(group["x"][1].expression.ub - 0.003) < 1e-5 # x is in kg

When a tagged a quantity can vary over several orders of magnitude, it can be helpful to provide conditional formatting. To do this a callable can be provided as the format_string which takes the quantity value and returns a format string. A simple example is given below.

m = model()

tagw = ModelTag(
  expr=m.w,
  format_string=lambda x: "{:,.0f}" if x >= 100 else "{:.2f}",
  display_units=pyo.units.g,
)

tagw.set(1*pyo.units.g)
assert str(tagw[1, "a"]) == "1.00 g"
tagw.set(1*pyo.units.kg)
assert str(tagw[1,"a"]) == "1,000 g"

Tags can also be used to generate tabulated model results. The example below provides an example of using the table_heading and table_row functions. The table_heading function provides a list of string tag keys that make up the columns of a table. This list can serve as the heading of a table. As an option, the units of measure can be included in the string. The table_row function provides a list of model values corresponding to tags. These values can either be numeric data or formatted strings. If they are formatted strings, they can also include units of measure. See the function documentation below for details. The code below provides a simple example.

import pyomo.environ as pyo
import pandas as pd
from idaes.core.util import ModelTag, ModelTagGroup

model = pyo.ConcreteModel()
model.x = pyo.Var([1, 2], initialize=0, units=pyo.units.m)
model.z = pyo.Var(units=pyo.units.m)
model.z.fix(5)
model.c = pyo.Constraint(expr=model.x[1] + model.x[2] == model.z)
solver = pyo.SolverFactory("ipopt")
tag_group = ModelTagGroup()
tag_group["z"] = ModelTag(
  expr=model.z, format_string="{:.3f}", display_units=pyo.units.cm)
tag_group["x"] = ModelTag(
  expr=model.x, format_string="{:.3f}", display_units=pyo.units.cm)

head = tag_group.table_heading()
assert head[0] == "z (cm)"
assert head[1] == "x[1] (cm)"
assert head[2] == "x[2] (cm)"
df = pd.DataFrame(columns=head)
for y in [0, 1, 2, 3, 4]:
  model.x[1].fix(y)
  solver.solve(model)
  row = tag_group.table_row(units=False, numeric=True)
  df.loc[len(df.index)] = row

assert abs(df.loc[0][0] - 500.000) < 1e-6
assert abs(df.loc[0][1] - 0.000) < 1e-6
assert abs(df.loc[0][2] - 500.000) < 1e-6

assert abs(df.loc[1][0] - 500.000) < 1e-6
assert abs(df.loc[1][1] - 100.000) < 1e-6
assert abs(df.loc[1][2] - 400.000) < 1e-6

Available Classes#

class idaes.core.util.tags.ModelTag(expr, format_string='{}', doc='', display_units=None)[source]#

The purpose of this class is to facilitate a simpler method of accessing, displaying, and reporting model quantities. The structure of IDAES models is a complex hierarchy. This class allows quantities to be accessed more directly and provides more control over how they are reported.

display(units=True, format_string=None, index=None)[source]#

Get a string representation of the tagged quantity

Parameters:
  • units (bool) – Include units of measure in the string

  • format_string (str) – Formatting string, if supplied overrides the default

  • index – If the tagged quantity is indexed, an index for the element to display is required, or the default index is used.

Returns:

str

property doc#

Tag documentation string

property expression#

The tagged expression

fix(val=None, in_display_units=None)[source]#

Fix the value of a tagged variable.

Parameters:
  • val – value, if None fix without setting a value

  • in_display_units – if true assume the value is in the display units

Returns:

None

property fixed#

Get the tagged variable if the tag is not a variable, raise TypeError

get_display_value(index=None, convert=True)[source]#

Get the value of the expression to display. Do unit conversion if needed. This caches the unit conversion, to save time if this is called repeatedly. The unconverted value is used to ensure the cached converted value is still valid.

Parameters:
  • index – index of value to display if expression is indexed

  • convert – if False don’t do unit conversion

Returns:

numeric expression value

get_format(units=True, index=None)[source]#

Get the formatting string.

Parameters:
  • units – if True include units of measure

  • index – index for indexed expressions

Returns

str:

get_unit_str(index=None)[source]#

String representation of the tagged quantity’s units of measure

property group#

The ModelTagGroup object that this belongs to, if any.

property indexes#

The index set of the tagged quantity

property is_indexed#

Returns whether the tagged expression is an indexed.

property is_var#

Whether the tagged expression is a Pyomo Var. Tagged variables can be fixed or set, while expressions cannot.

items()[source]#

Iterator for key scalar elements pairs in a tag

keys()[source]#

Iterator of keys in the tag. If scalar, is a single None.

property native_value#

The numeric value of the tagged expression in the native units

set(val, in_display_units=None)[source]#

Set the value of a tagged variable.

Parameters:
  • val – value

  • in_display_units – if true assume the value is in the display units

Returns:

None

property set_in_display_units#

Default index to use in the tag’s string representation, this is required for indexed quantities if you want to automatically convert to string. An example use it for a time indexed tag, to display a specific time point.

setlb(val, in_display_units=None)[source]#

Set the lower bound of a tagged variable.

Parameters:
  • v – value

  • in_display_units – if true assume the value is in the display units

Returns:

None

setub(val, in_display_units=None)[source]#

Set the value of a tagged variable.

Parameters:
  • v – value

  • in_display_units – if true assume the value is in the display units

Returns:

None

property str_include_units#

Set whether to include units by default in the tag’s string representation

unfix()[source]#

Unfix the value of a tagged variable.

Parameters:

v – value, if None fix without setting a value

Returns:

None

property value#

The numeric value of the tagged expression in the display units

values()[source]#

Iterator for scalar elements in a tag (The elements are scalar tags)

property var#

Get the tagged variable if the tag is not a variable, raise TypeError

class idaes.core.util.tags.ModelTagGroup[source]#

This a basically a dictionary of ModelTag objects. This is used to group sets of tags, and contains methods to operate on sets of tags. It inherits dict so dictionary methods can be used.

add(name, expr, **kwargs)[source]#

Add a new model tag to the group

property set_in_display_units#

When this is True, and set() or fix() are called on a tag in the group, with a value that doesn’t include units, assume the display units.

property str_include_units#

When converting a tag in this group directly to a string, include units or not.

table_heading(tags=None, units=True)[source]#

Create a table heading with a given set of tags, for tabulating model results.

Parameters:
  • tags – List (not tuple, since a tuple can be a key) of tag keys or 2-element list of tags key and an index. If a key is for an indexed value and no index is given with the key, it will be flattened to create a column for each index.

  • units – If True, include the units of measure in the column heading names.

Returns:

list of column headings

table_row(tags=None, units=True, numeric=False)[source]#

Create a table row with a given set of tags, for tabulating model results. The row contains values of tagged quantities either as strings of numeric values.

Parameters:
  • tags – List (not tuple, since a tuple can be a key) of tag keys or 2-element list of tags key and an index. If a key is for an indexed value and no index is given with the key, it will be flattened to create a column for each index.

  • units – If true include the units of measure in the value, if the values are not numeric.

  • numeric – If true provide numeric values rather than a formatted string.

Returns:

list of values for a table row either numeric or as formatted strings

idaes.core.util.tags.svg_tag(svg=None, tag_group=None, outfile=None, idx=None, tag_map=None, show_tags=False, byte_encoding='utf-8')[source]#

Replace text in a SVG with tag values for the model. This works by looking for text elements in the SVG with IDs that match the tags or are in tag_map.

Parameters:
  • svg – a file pointer or a string containing svg contents

  • tag_group – a ModelTagGroup with tags to display in the SVG

  • outfile – a file name to save the results, if None don’t save

  • idx – if None not indexed, otherwise an index in the indexing set of the reference

  • tag_map – dictionary with svg id keys and tag values, to map svg ids to tags, used in cases where tags contain characters that cannot be used in the svg’s xml

  • show_tags – Put tag labels of the diagram instead of numbers

  • byte_encoding – If svg is given as a byte-array, use this encoding to convert it to a string.

Returns:

SVG String