Source code for thermosteam._preferences

# -*- coding: utf-8 -*-
# BioSTEAM: The Biorefinery Simulation and Techno-Economic Analysis Modules
# Copyright (C) 2020-2023, Yoel Cortes-Pena <yoelcortes@gmail.com>
# 
# This module is under the UIUC open-source license. See 
# github.com/BioSTEAMDevelopmentGroup/biosteam/blob/master/LICENSE.txt
# for license details.
"""
"""
import thermosteam as tmo
from thermosteam.units_of_measure import parse_units_notation
import yaml
import os

__all__ = ('preferences', 'TemporaryPreferences')

[docs] class DisplayPreferences: """ All preferences for BioSTEAM diagram and results display. Examples -------- >>> from biosteam import preferences >>> preferences.show() DisplayPreferences: label_streams: True autodisplay: True minimal_nodes: False number_path: False profile: False raise_exception: False background_color: 'transparent' stream_color: '#90918e' label_color: '#90918e' depth_colors: ['#f98f609f'] stream_width: 'F_mass' unit_color: '#555f69' unit_label_color: 'white' unit_periphery_color: '#90918e' fill_cluster: False graphviz_format: 'svg' tooltips_full_results: False graphviz_html_height: {'big-system': ('600px', '900px'), 'system': ('400px', '600px'), 'unit': ('225px', '400px')} show_all_streams: True flow: 'kmol/hr:.3g' T: 'K:.5g' P: 'Pa:.6g' composition: False N: 7 sort: False """ __slots__ = ('label_streams', 'autodisplay', 'minimal_nodes', 'number_path', 'profile', 'raise_exception', 'background_color', 'stream_color', 'label_color', 'label_color', 'depth_colors', 'stream_width', 'unit_color', 'unit_label_color', 'unit_periphery_color', 'fill_cluster', 'graphviz_format', 'tooltips_full_results', 'graphviz_html_height', 'show_all_streams') def __init__(self): #: Whether to label the ID of streams with sources and sinks in process #: flow diagrams. self.label_streams: bool = True #: Whether to automatically generate diagrams when displaying an object in the #: IPython console. self.autodisplay: bool = True #: Whether to ignore unit graphics and display unit nodes as dots in process #: flow diagrams. self.minimal_nodes: bool = False #: Whether to number unit operations according to their order in the system path. self.number_path: bool = False #: Whether to clock the simulation time of unit operations in diagrams. self.profile: bool = False #: Whether to raise exception regarding problems displaying graphviz diagrams. self.raise_exception: bool = False #: Background color in graphviz diagrams. self.background_color: str = 'transparent' #: Color of streams in graphviz diagrams. self.stream_color: str = '#90918e' #: Color of stream labels in graphviz diagrams. self.label_color: str = '#90918e' #: Color of subsystem clusters in BioSTEAM graphviz diagrams. self.depth_colors: list[str] = ['#f98f609f'] #: Property to scale stream widths in BioSTEAM graphviz diagrams. self.stream_width: str = 'F_mass' #: Unit node fill color in BioSTEAM graphviz diagrams. self.unit_color: str = '#555f69' #: Unit node label color in BioSTEAM graphviz diagrams. self.unit_label_color: str = 'white' #: Unit node periphery color in BioSTEAM graphviz diagrams. self.unit_periphery_color: str = '#90918e' #: Whether to fill subsystem boxes in BioSTEAM 'cluster' diagrams. self.fill_cluster: bool = False #: Image format of BioSTEAM graphviz diagrams. self.graphviz_format: str = 'svg' #: Whether to add full results in tooltips by inserting java script into graphviz html outputs. self.tooltips_full_results: bool = False #: Displayed height of graphviz html diagrams without and with full results. self.graphviz_html_height: dict[str, tuple[str, str]] = { 'big-system': ('600px', '900px'), 'system': ('400px', '600px'), 'unit': ('225px', '400px'), } #: Whether to show all streams, including empty feeds and products. self.show_all_streams = True
[docs] def temporary(self): """Return a TemporaryPreferences object that will revert back to original preferences after context management.""" return TemporaryPreferences()
[docs] def reset(self, save=False): """Reset to BioSTEAM defaults.""" self.__init__() self.flow = 'kmol/hr' self.T = 'K' self.P = 'Pa' self.composition = False self.N = 7 self.sort = False if save: self.save()
@property def flow(self) -> str: """Flow rate units and notation.""" return ":".join([tmo.Stream.display_units.flow, tmo.Stream.display_notation.flow]) @flow.setter def flow(self, units_notation): units, notation = parse_units_notation(units_notation) if units is not None: tmo.Stream.display_units.flow = units if notation is not None: tmo.Stream.display_notation.flow = notation @property def T(self) -> str: """Temperature units and notation.""" return ":".join([tmo.Stream.display_units.T, tmo.Stream.display_notation.T]) @T.setter def T(self, units_notation): units, notation = parse_units_notation(units_notation) if units is not None: tmo.Stream.display_units.T = units if notation is not None: tmo.Stream.display_notation.T = notation @property def P(self) -> str: """Pressure units and notation.""" return ":".join([tmo.Stream.display_units.P, tmo.Stream.display_notation.P]) @P.setter def P(self, units_notation): units, notation = parse_units_notation(units_notation) if units is not None: tmo.Stream.display_units.P = units if notation is not None: tmo.Stream.display_notation.P = notation @property def composition(self) -> bool: """Whether to show composition.""" return tmo.Stream.display_units.composition @composition.setter def composition(self, composition): tmo.Stream.display_units.composition = composition @property def sort(self) -> bool: """Whether to sort flows in decreasing order.""" try: return tmo.Stream.display_units.sort except: return False @sort.setter def sort(self, sort): try: tmo.Stream.display_units.sort = sort except: pass @property def N(self) -> int: """Number of compounds to display.""" return tmo.Stream.display_units.N @N.setter def N(self, N): tmo.Stream.display_units.N = N def update(self, *, save=False, **kwargs): for i, j in kwargs.items(): setattr(self, i, j) if save: self.save() def _set_mode(self, stream, label, bg, cluster, unit_color, unit_label_color, unit_periphery_color, fill_cluster, save): self.background_color = bg self.stream_color = stream self.label_color = label self.depth_colors = cluster self.unit_color = unit_color self.unit_label_color = unit_label_color self.unit_periphery_color = unit_periphery_color self.fill_cluster = fill_cluster if save: self.save()
[docs] def classic_mode(self, stream='#90918e', label='#90918e', bg='transparent', cluster=('#f98f609f',), unit_color='#555f69', unit_label_color='white', unit_periphery_color='none', fill_cluster=False, save=False): """Set diagram display colors to classic mode.""" self._set_mode(stream, label, bg, cluster, unit_color, unit_label_color, unit_periphery_color, fill_cluster, save)
[docs] def dark_mode(self, stream='#98a2ad', label='#e5e5e5', bg='transparent', cluster=['#5172512f', '#1111112f'], unit_color='#555f69', unit_label_color='white', unit_periphery_color='none', fill_cluster=True, save=False): """Set diagram display colors to dark mode.""" self._set_mode(stream, label, bg, cluster, unit_color, unit_label_color, unit_periphery_color, fill_cluster, save)
[docs] def light_mode(self, stream='#4e4e4e', label='#4e4e4e', bg='#ffffffff', cluster=['#d5edf02f', '#ffffffdf'], unit_color='white:#CDCDCD', unit_label_color='black', unit_periphery_color='#4e4e4e', fill_cluster=True, save=False): """Set diagram display colors to light mode.""" self._set_mode(stream, label, bg, cluster, unit_color, unit_label_color, unit_periphery_color, fill_cluster, save)
night_mode = dark_mode day_mode = light_mode def autoload(self): folder = os.path.dirname(__file__) file = os.path.join(folder, 'preferences.yaml') with open(file, 'r') as stream: data = yaml.full_load(stream) assert isinstance(data, dict), 'yaml file must return a dict' self.update(**data)
[docs] def to_dict(self): """Return dictionary of all preferences.""" dct = {i: getattr(self, i) for i in preferences.__slots__} dct['flow'] = self.flow dct['T'] = self.T dct['P'] = self.P dct['composition'] = self.composition dct['N'] = self.N dct['sort'] = self.sort return dct
[docs] def save(self): """Save preferences.""" folder = os.path.dirname(__file__) file = os.path.join(folder, 'preferences.yaml') with open(file, 'w') as file: dct = self.to_dict() yaml.dump(dct, file)
[docs] def show(self): """Print all specifications.""" dct = self.to_dict() print(f'{type(self).__name__}:\n' + '\n'.join([f"{i}: {repr(j)}" for i, j in dct.items()]))
_ipython_display_ = show
class TemporaryPreferences: def __enter__(self): dct = self.__dict__ dct.update({i: getattr(preferences, i) for i in preferences.__slots__}) dct['flow'] = preferences.flow dct['T'] = preferences.T dct['P'] = preferences.P dct['composition'] = preferences.composition dct['N'] = preferences.N dct['sort'] = preferences.sort return preferences def __exit__(self, type, exception, traceback): preferences.update(**self.__dict__) if exception: raise exception #: preferences: DisplayPreferences = DisplayPreferences() if os.environ.get("FILTER_WARNINGS"): from warnings import filterwarnings; filterwarnings('ignore') if not os.environ.get("DISABLE_PREFERENCES") == "1": try: preferences.autoload() except: pass