watertap.ui package
Submodules
watertap.ui.fsapi module
Simple flowsheet interface API
- class watertap.ui.fsapi.Actions(value)[source]
Bases:
str
,Enum
Known actions that can be run. Actions that users should not run directly (unless they know what they are doing) are prefixed with an underscore.
- class watertap.ui.fsapi.FSI
Forward-reference to a FlowsheetInterface type, used in
FlowsheetInterface.find()
alias of TypeVar(‘FSI’, bound=
FlowsheetInterface
)
- class watertap.ui.fsapi.FlowsheetExport(*, m: object = None, obj: object = None, name: None | str = '', description: None | str = '', exports: Dict[str, ModelExport] = {}, version: int = 2, requires_idaes_solver: bool = False, dof: int = 0, sweep_results: None | dict = {}, build_options: Dict[str, ModelOption] = {})[source]
Bases:
BaseModel
A flowsheet and its contained exported model objects.
- add(*args, data: dict | ModelExport | None = None, **kwargs) object [source]
Add a new variable (or other model object).
There are a few different ways of invoking this function. Users will typically use this form:
add(obj=<pyomo object>, name="My value name", ..etc..)
where the keywords after obj match the non-computed names in
ModelExport
.If these same name/value pairs are already in a dictionary, this form is more convenient:
add(data=my_dict_of_name_value_pairs)
If you have an existing ModelExport object, you can add it more directly with:
add(my_object) # -- OR -- add(data=my_object)
- Parameters:
*args – If present, should be a single non-named argument, which is a ModelExport object. Create by adding it.
data – If present, create from this argument. If it’s a dict, create from its values just as from the kwargs. Otherwise, it should be a ModelExport object, and create by adding it.
kwargs – Name/value pairs to create a ModelExport object. Accepted names and default values are in the ModelExport.
- Raises:
KeyError – If the name of the Pyomo object is the same as an existing one, i.e. refuse to overwrite.
- add_option(name: str, **kwargs) ModelOption [source]
Add an ‘option’ to the flowsheet that can be displayed and manipulated from the UI.
Constructs a
ModelOption
instance with provided args and adds it to the dict of options, keyed by its name.- Parameters:
name – Name of option (internal, for accessing the option)
kwargs – Fields of
ModelOption
- from_csv(file: str | Path, flowsheet)[source]
Load multiple exports from the given CSV file.
CSV file format rules:
Always use a header row. The names are case-insensitive, order is not important. The ‘name’, ‘obj’, and ‘ui_units’ columns are required.
Columns names should match the non-computed names in
ModelExport
. See .add() for a list.The object to export should be in a column named ‘obj’, prefixed with ‘fs.’
For units, use Pyomo units module as ‘units’, e.g., ‘mg/L’ is units.mg / units.L
For example:
name,obj,description,ui_units,display_units,rounding,is_input,input_category,is_output,output_category Leach liquid feed rate,fs.leach_liquid_feed.flow_vol[0],Leach liquid feed volumetric flow rate,units.L/units.hour,L/h,2,TRUE,Liquid feed,FALSE, Leach liquid feed H,"fs.leach_liquid_feed.conc_mass_comp[0,'H']",Leach liquid feed hydrogen mass composition,units.mg/units.L,mg/L,3,TRUE,Liquid feed,FALSE, .......etc.......
- Parameters:
file – Filename or path. If not an absolute path, start from the directory of the caller’s file.
flowsheet – Flowsheet used to evaluate the exported objects.
- Returns:
Number of exports added
- Return type:
int
- Raises:
IOError – if input file doesn’t exist
ValueError – Invalid data in input file (error message will have details)
- model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[dict[str, FieldInfo]] = {'build_options': FieldInfo(annotation=Dict[str, ModelOption], required=False, default={}), 'description': FieldInfo(annotation=Union[NoneType, str], required=False, default='', validate_default=True), 'dof': FieldInfo(annotation=int, required=False, default=0), 'exports': FieldInfo(annotation=Dict[str, ModelExport], required=False, default={}), 'm': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'name': FieldInfo(annotation=Union[NoneType, str], required=False, default='', validate_default=True), 'obj': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'requires_idaes_solver': FieldInfo(annotation=bool, required=False, default=False), 'sweep_results': FieldInfo(annotation=Union[NoneType, dict], required=False, default={}), 'version': FieldInfo(annotation=int, required=False, default=2)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
This replaces Model.__fields__ from Pydantic V1.
- class watertap.ui.fsapi.FlowsheetInterface(fs: FlowsheetExport | None = None, do_build: Callable | None = None, do_export: Callable | None = None, do_solve: Callable | None = None, get_diagram: Callable | None = None, category: FlowsheetCategory | None = None, custom_do_param_sweep_kwargs: Dict | None = None, **kwargs)[source]
Bases:
object
Interface between users, UI developers, and flowsheet models.
- class MissingObject(key, name)
Bases:
tuple
Type of item in list
MissingObjectError.missing
.key
is the unique key assigned to the variable,name
is the variable name in the flowsheet- key
Alias for field number 0
- name
Alias for field number 1
- exception MissingObjectError(missing)[source]
Bases:
Exception
Error returned if data in load refers to a variable not found in the target object.
Use the .missing attribute of the error object to get the list of MissingObjects.
- UI_HOOK = 'export_to_ui'
Function to look for in modules. See
find()
.
- __init__(fs: FlowsheetExport | None = None, do_build: Callable | None = None, do_export: Callable | None = None, do_solve: Callable | None = None, get_diagram: Callable | None = None, category: FlowsheetCategory | None = None, custom_do_param_sweep_kwargs: Dict | None = None, **kwargs)[source]
Constructor.
- Parameters:
fs – An existing wrapper to a flowsheet object. If this is not provided, then one will be constructed by passing the keyword arguments to the built-in pydantic
model_validate()
method ofFlowsheetExport
.do_build – Function to call to build the flowsheet. It should build the flowsheet model and return the FlowsheetBlock, which is typically the fs attribute of the model object. Required
do_export – Function to call to export variables after the model is built. This will be called automatically by
build()
. Requireddo_solve – Function to solve the model. It should return the result that the solver itself returns. Required
custom_do_param_sweep_kwargs – Option for setting up parallel solver using custom solve function.
**kwargs – See fs arg. If the fs arg is provided, these are ignored.
- add_action(action_name: str, action_func: Callable)[source]
Add an action for the flowsheet.
- Parameters:
action_name – Name of the action to take (see
Actions
)action_func – Function to call for the action
- Returns:
None
- build(**kwargs)[source]
Build flowsheet
- Parameters:
**kwargs – User-defined values
- Returns:
None
- Raises:
RuntimeError – If the build fails
- export_values()[source]
Copy current values in underlying Pyomo model into exported model.
- Side-effects:
Attribute
fs_exp
is modified.
- classmethod from_installed_packages(group_name: str = 'watertap.flowsheets') Dict[str, FlowsheetInterface] [source]
Get all flowsheet interfaces defined as entry points within the Python packages installed in the environment.
This uses the
importlib.metadata.entry_points()
function to fetch the list of flowsheets declared as part of a Python package distribution’s entry points under the groupgroup_name
.To set up a flowsheet interface for discovery, locate your Python package distribution’s file (normally
setup.py
,pyproject.toml
, or equivalent) and add an entry in theentry_points
section.For example, to add a flowsheet defined in
watertap/flowsheets/flowsheets/my_flowsheet.py
so that it can be discovered with the namemy_flowsheet
wherever thewatertap
package is installed, the following should be added to WaterTAP’ssetup.py
:setup( name="watertap", # other setup() sections entry_points={ "watertap.flowsheets": [ # other flowsheet entry points "my_flowsheet = watertap.flowsheets.flowsheets.my_flowsheet", ] } )
- Parameters:
group_name – The entry_points group from which the flowsheet interface modules will be populated.
- Returns:
Mapping with keys the module names and values FlowsheetInterface objects
- classmethod from_module(module: str | module) FlowsheetInterface | None [source]
Get a a flowsheet interface for module.
- Parameters:
module – The module
- Returns:
A flowsheet interface or None if it failed
- get_action(name: str) Callable | None [source]
Get the function for an
add()
-ed action.- Parameters:
name – Name of the action (see
Actions
)- Returns:
Function for this action
- Raises:
KeyError, if no such action is defined –
- get_diagram(**kwargs)[source]
Return diagram image name.
- Parameters:
**kwargs – User-defined values
- Returns:
Return image file name if get_diagram function is callable. Otherwise, return none
- load(data: Dict)[source]
Load values from the data into corresponding variables in this instance’s FlowsheetObject.
- Parameters:
data – The input flowsheet (probably deserialized from JSON)
- class watertap.ui.fsapi.ModelExport(*, obj: object | None = None, name: str = '', value: float = 0.0, ui_units: object = None, display_units: str = '', rounding: float = 0, description: str = '', is_input: bool = True, is_output: bool = True, is_readonly: None | bool = None, input_category: str | None = None, output_category: str | None = None, chart_type: str | None = None, chart_group: str | None = None, obj_key: None | str = None, fixed: bool = True, lb: None | float = 0.0, ub: None | float = 0.0, num_samples: int = 2, has_bounds: bool = True, is_sweep: bool = False)[source]
Bases:
BaseModel
A variable, expression, or parameter.
- model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[dict[str, FieldInfo]] = {'chart_group': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'chart_type': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'description': FieldInfo(annotation=str, required=False, default=''), 'display_units': FieldInfo(annotation=str, required=False, default=''), 'fixed': FieldInfo(annotation=bool, required=False, default=True), 'has_bounds': FieldInfo(annotation=bool, required=False, default=True), 'input_category': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'is_input': FieldInfo(annotation=bool, required=False, default=True), 'is_output': FieldInfo(annotation=bool, required=False, default=True), 'is_readonly': FieldInfo(annotation=Union[NoneType, bool], required=False, default=None, validate_default=True), 'is_sweep': FieldInfo(annotation=bool, required=False, default=False), 'lb': FieldInfo(annotation=Union[NoneType, float], required=False, default=0.0), 'name': FieldInfo(annotation=str, required=False, default=''), 'num_samples': FieldInfo(annotation=int, required=False, default=2), 'obj': FieldInfo(annotation=Union[object, NoneType], required=False, default=None, exclude=True), 'obj_key': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'output_category': FieldInfo(annotation=Union[str, NoneType], required=False, default=None), 'rounding': FieldInfo(annotation=float, required=False, default=0), 'ub': FieldInfo(annotation=Union[NoneType, float], required=False, default=0.0), 'ui_units': FieldInfo(annotation=object, required=False, default=None, exclude=True), 'value': FieldInfo(annotation=float, required=False, default=0.0)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
This replaces Model.__fields__ from Pydantic V1.
- model_post_init(context: Any, /) None
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that’s what pydantic-core passes when calling it.
- Parameters:
self – The BaseModel instance.
context – The context.
- class watertap.ui.fsapi.ModelOption(*, name: str, category: str = 'Build Options', display_name: None | str = None, description: None | str = None, display_values: List[Any] = [], values_allowed: str | List[Any], min_val: None | int | float = None, max_val: None | int | float = None, value: Any = None)[source]
Bases:
BaseModel
An option for building/running the model.
- model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}
A dictionary of computed field names and their corresponding ComputedFieldInfo objects.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_fields: ClassVar[dict[str, FieldInfo]] = {'category': FieldInfo(annotation=str, required=False, default='Build Options'), 'description': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'display_name': FieldInfo(annotation=Union[NoneType, str], required=False, default=None, validate_default=True), 'display_values': FieldInfo(annotation=List[Any], required=False, default=[]), 'max_val': FieldInfo(annotation=Union[NoneType, int, float], required=False, default=None), 'min_val': FieldInfo(annotation=Union[NoneType, int, float], required=False, default=None), 'name': FieldInfo(annotation=str, required=True), 'value': FieldInfo(annotation=Any, required=False, default=None), 'values_allowed': FieldInfo(annotation=Union[str, List[Any]], required=True)}
Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].
This replaces Model.__fields__ from Pydantic V1.