Source code for pydsol.core.parameters
"""
InputParameters describe different types of input parameters for the model.
All parameters for a model are contained in a hierarchical map where
successive keys can be retrieved using a dot-notation between the key
elements.
Example
-------
Suppose a model has two servers: server1 and server2. Each of the
servers has an average service time and a number of resources. This can be
codes using keys 'server1.avg_serice_time', 'server1.nr_resources',
'server2.avg_serice_time', 'server2.nr_resources'. This means that the
key 'server1' contains an InputParameterMap with an instance of
InputParameterFloat for the service time, and InputParameterInt for the
number of resources. Readers for the input parameter map can read the model
parameters, e.g., from the screen, a web page, an Excel file, a properties
file, or a JSON file.
"""
import math
from typing import Union, Dict, Type, List
from pydsol.core.units import Quantity
from pydsol.core.utils import get_module_logger
from pydsol.core.interfaces import InputParameterInterface
__all__ = [
"InputParameter",
"InputParameterMap",
"InputParameterInt",
"InputParameterFloat",
"InputParameterStr",
"InputParameterBool",
"InputParameterQuantity",
"InputParameterSelectionList",
"InputParameterUnit",
]
logger = get_module_logger('parameters')
[docs]
class InputParameter(InputParameterInterface):
"""
The InputParameter is a user readable and settable property for the
simulation model. All parameters for a model are contained in a
hierarchical map where successive keys can be retrieved using a
dot-notation between the key elements.
Attributes
----------
_key: str
The key of the parameter that can be a part of the dot-notation to
uniquely identify the model parameter. The key does not contain the
name of the parent, and should not contain any periods. It should
also be unique within its node of the input parameter tree. The key
is immutable.
_name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
_default_value: object
The default (initial) value of the parameter. The actual type will
be defined in subclasses of `InputParameter`. The default value is
immutable.
_display_priority: float
A number indicating the order of display of the parameter in the
parent parameter map. Floats are allowed to make it easy to insert
an extra parameter between parameters that have already been
allocated subsequent integer values.
_parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its key.
Typically, only the root InputParameterMap has no parent, and all
other parameters have an InputParameterMap as parent.
_description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely there
for the user interface.
_read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be changed).
_value: object
The actual value of the parameter. The value is initialized with
default_value and is updated based on user input or data input.
The actual type will be defined in subclasses of `InputParameter`.
"""
[docs]
def __init__(self, key: str, name: str, default_value,
display_priority: Union[int, float], *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False):
"""
Create a new InputParameter.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: object
The default (initial) value of the parameter. The actual type
will be defined in subclasses of `InputParameter`.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
"""
if not isinstance(key, str):
raise TypeError(f"parameter key {key} not a string")
if len(key) == 0:
raise ValueError("parameter key length 0")
if '.' in key:
raise ValueError(f"parameter key {key} contains a period")
if not isinstance(name, str):
raise TypeError(f"parameter name {name} not a string")
if len(name) == 0:
raise ValueError("parameter name length 0")
if not (isinstance(display_priority, float)
or isinstance(display_priority, int)):
raise TypeError(f"priority {display_priority} not a float/int")
if parent is not None and not isinstance(parent, InputParameterMap):
raise TypeError("parent not an InputParamterMap")
if not isinstance(read_only, bool):
raise TypeError(f"parameter read_only {read_only} not a bool")
self._key: str = key
self._name: str = name
if description == None:
self._description: str = ""
else:
self._description: str = description
self._default_value = default_value
self._display_priority: float = float(display_priority)
self._read_only: bool = read_only
self._value = default_value
self._parent: "InputParameterMap" = parent
if parent is not None:
# will take care of error for duplicate keys
parent.add(self)
@property
def key(self) -> str:
"""
Return the key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent. The key is set at time
of construction and it is immutable.
Returns
-------
str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter.
"""
return self._key
[docs]
def extended_key(self):
"""
Return the extended key of this InputParameter including parents
with a dot-notation. The name of this parameter is the last entry
in the dot notation.
Returns
-------
str
The extended key of this InputParameter including parents
with a dot-notation.
"""
if self._parent == None:
return self._key
else:
return self._parent.extended_key() + '.' + self._key
@property
def name(self) -> str:
"""
Returns the concise description of the input parameter, which can
be used in a GUI to identify the parameter to the user.
Returns
-------
str
The concise description of the input parameter, which can
be used in a GUI to identify the parameter to the user.
"""
return self._name
@property
def description(self) -> str:
"""
Returns a description or explanation of the InputParameter. For
instance, an indication of the bounds or the type. This value is
purely there for the user interface.
Returns
-------
str
A description or explanation of the InputParameter.
"""
return self._description
@property
def default_value(self) -> object:
"""
Returns the default (initial) value of the parameter. The actual
return type will be defined in subclasses of `InputParameter`.
The default value is immutable.
Returns
-------
object
The default (initial) value of the parameter.
"""
return self._default_value
@property
def value(self) -> object:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
The actual type will be defined in subclasses of `InputParameter`.
Returns
-------
object
The actual value of the parameter.
"""
return self._value
[docs]
def set_value(self, value: object):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: object
The new value of the parameter.
Raises
------
ValueError
when parameter is read-only
"""
if self.read_only:
raise ValueError("parameter {self.key} is read only")
self._value = value
@property
def display_priority(self) -> float:
"""
Return the number indicating the order of display of the parameter
in the parent parameter map. Floats make it easy to insert an extra
parameter between parameters that have already been allocated
subsequent integer values.
Returns
-------
float
The number indicating the order of display of the parameter
in the parent parameter map.
"""
return self._display_priority
@property
def read_only(self) -> bool:
"""
Return whether a user is prohibited from changing the value of the
parameter or not.
Returns
-------
bool
Whether a user is prohibited from changing the value of the
parameter or not.
"""
return self._read_only
@property
def parent(self) -> "InputParameterMap":
"""
Return the parent map in which the parameter can be retrieved using
its key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
Returns
-------
InputParameterMap
the parent map in which the parameter can be retrieved using
its key.
"""
return self._parent
def __eq__(self, other):
if not isinstance(other, InputParameter):
return False
return self.display_priority == other.display_priority
def __ne__(self, other):
if not isinstance(other, InputParameter):
return True
return self.display_priority != other.display_priority
def __gt__(self, other):
if not isinstance(other, InputParameter):
raise TypeError(f"cannot compare parameter with {other}")
return self.display_priority > other.display_priority
def __ge__(self, other):
if not isinstance(other, InputParameter):
raise TypeError(f"cannot compare parameter with {other}")
return self.display_priority >= other.display_priority
def __lt__(self, other):
if not isinstance(other, InputParameter):
raise TypeError(f"cannot compare parameter with {other}")
return self.display_priority < other.display_priority
def __le__(self, other):
if not isinstance(other, InputParameter):
raise TypeError(f"cannot compare parameter with {other}")
return self.display_priority <= other.display_priority
def __str__(self) -> str:
return self.extended_key() + " [" + self.name + "] = " \
+str(self.value)
def __repr__(self) -> str:
return str(self)
[docs]
class InputParameterMap(InputParameter):
"""
The InputParameterMap contains a number of InputParameters, each of
which can also be an InputParameterMap again. The InputParameterMap
provides functions to add and remove sub-parameters, to retrieve
sub-parameters based on their key, and to return a sorted set of
InputParameters based on their displayValue.
The `InputParameterMap` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `dict[str, InputParameter]`.
"""
[docs]
def __init__(self, key: str, name: str, display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None):
"""
Create a new `InputParameterMap`. This can be the root map, or
a sub-map. The `InputParameterMap` has no default value, and is
read-only by definition.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
"""
super().__init__(key, name, None, display_priority,
parent=parent, description=description,
read_only=True)
self._value: Dict[str, InputParameter] = {}
@property
def value(self) -> Dict[str, InputParameter]:
"""
Returns the dict defined in this `InputParameterMap`,
which is the value.
Returns
-------
dict[str, InputParameter]
The dict defined in this `InputParameterMap`.
"""
return self._value
[docs]
def set_value(self, value):
"""
Note that `InputParameterMap` does not have a setter for the value.
Warning
-------
`InputParameterMap` does not have a setter for the value.
Raises
------
NotImplementedError
when called.
"""
raise NotImplementedError("InputParameterMap value cannot be set")
[docs]
def add(self, input_parameter: InputParameter):
"""
Add an input parameter to the map, and sort the members based on the
display_priorities.
Parameters
----------
input_parameter: InputParameter
The input parameter to add to the map.
Raises
------
TypeError
when input_parameter is not an InputParameter.
ValueError
when the input parameter has a key that is already present in
the map
"""
if not isinstance(input_parameter, InputParameter):
raise TypeError("input parameter not of the correct type")
if input_parameter.key in self._value.keys():
raise ValueError(f"duplicate key {input_parameter.key} in map {self}")
input_parameter._parent = self
self._value[input_parameter.key] = input_parameter
# sort on the defined ordering in InputParameter after adding
self._value = {k: v for k, v in sorted(self._value.items(),
key=lambda item: item[1])}
[docs]
def get(self, key: str) -> InputParameter:
"""
Return an input parameter from the map based on its key. The key can
an extended key with a dot-notation. In that case, get will travese
into the tree and return the parameter from the correct sub-map.
Returns
-------
InputParameter
The input parameter from the map or sub-map based on its key.
Raises
------
KeyError
when the key or the first sub-part of the key cannot be found in
the map
KeyError
when a sub-part of the key does not point to an InputParameterMap
"""
if '.' in key:
parts = key.split('.')
if not parts[0] in self._value:
raise KeyError(f"could not find parameter {parts[0]} in {self}")
if not isinstance(self._value[parts[0]], InputParameterMap):
raise KeyError(f"Key {parts[0]} does not point at a submap")
return self._value[parts[0]].get(key[key.find('.') + 1:])
else:
if not key in self._value:
raise KeyError(f"could not find parameter {key} in {self}")
return self._value[key]
[docs]
def remove(self, key) -> InputParameter:
"""
Remove an input parameter from the map based on its key. The key can
an extended key with a dot-notation. In that case, remove will travese
into the tree and removes the parameter from the correct sub-map. When
the key in the final (sub)map cannot be found, the method returns
None and exits silently.
Returns
-------
InputParameter
The input parameter that was removed from the map or sub-map
based on its key, or None when the key was not found.
Raises
------
KeyError
when the sub-part of the key cannot be found in the map
KeyError
when a sub-part of the key does not point to an InputParameterMap
"""
if '.' in key:
parts = key.split('.')
if not parts[0] in self._value:
raise KeyError(f"could not find parameter {parts[0]} in {self}")
if not isinstance(self._value[parts[0]], InputParameterMap):
raise KeyError(f"Key {parts[0]} does not point at a submap")
return self._value[parts[0]].remove(key[key.find('.') + 1:])
return self._value.pop(key)
[docs]
def print_values(self, *, depth:int=0) -> str:
"""
Make a string with the keys and values of the map, including sub-maps
and their parameters. Indentation indicates the depth of the map and
of the parameters.
Parameters
----------
depth: int (optional)
The depth of the map traversal. For each further depth, two
spaces will be added to the indentation of the output.
Returns
-------
str
A string with the keys and values of the map, including sub-maps
and their parameters.
"""
s = ""
for key, param in self._value.items():
if isinstance(param, InputParameterMap):
s += f"{depth * ' '}MAP: {key}\n"
s += param.print_values(depth=depth + 2)
else:
s += f"{depth * ' '}{key} = {param.value}\n"
return s
[docs]
class InputParameterInt(InputParameter):
"""
InputParameterInt defines an integer input parameter with possible
lowest and highest values.
The `InputParameterInt` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `int`. It also has the following
extra attributes:
Attributes
----------
_min: int
The lowest value (inclusive) that can be entered for this parameter.
_max: int
The highest value (inclusive) that can be entered for this parameter.
_format: str
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc.
"""
[docs]
def __init__(self, key: str, name: str, default_value: int,
display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False,
min_value:int=-math.inf, max_value:int=math.inf,
format_str:str="%d"):
"""
Create a new InputParameterInt that can contain an integer input
value for the simulation model.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: int
The default (initial) value of the parameter.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
min_value: int (optional)
The lowest value (inclusive) that can be entered for this
parameter.
max_value: int (optional)
The highest value (inclusive) that can be entered for this
parameter.
format_str: str (optional)
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc.
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not an int
TypeError
when min_value or max_value is not an int or float
TypeError
when format_str is not a string
ValueError
when min_value >= max_value
ValueError
when default value not between min_value and max_value (inclusive)
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not isinstance(default_value, int):
raise TypeError(f"default value {default_value} is not an int")
if not isinstance(min_value, (int, float)):
raise TypeError(f"min value {min_value} is not an int or float")
if not isinstance(max_value, (int, float)):
raise TypeError(f"max value {max_value} is not an int or float")
if not isinstance(format_str, str):
raise TypeError(f"format string {format_str} is not a str")
if min_value >= max_value:
raise ValueError(f"min {min_value} >= max {max_value}")
if not min_value <= default_value <= max_value:
raise ValueError(f"default value {default_value} not between " + \
f"{min_value} and {max_value}")
self._min: int = min_value
self._max: int = max_value
self._format: str = format_str
@property
def value(self) -> int:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
int
The actual value of the parameter.
"""
return self._value
@property
def min_value(self) -> int:
"""
Returns the defined minimum allowed value (inclusive) of the parameter.
Returns
-------
int
The minimum allowed value of the parameter.
"""
return self._min
@property
def max_value(self) -> int:
"""
Returns the defined maximum allowed value (inclusive) of the parameter.
Returns
-------
int
The maximum allowed value of the parameter.
"""
return self._max
@property
def format_str(self) -> str:
"""
Returns the defined format string of the parameter value.
Returns
-------
str
The defined format string of the parameter value.
"""
return self._format
[docs]
def set_value(self, value: int):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: int
The new value of the parameter.
Raises
------
ValueError
if the parameter is read-only
TypeError
if the new value is not an int
ValueError
if the new value is not between the min_value and max_value
"""
if self.read_only:
raise ValueError(f"parameter {self.key} is read only")
if not isinstance(value, int):
raise TypeError(f"parameter value {value} not an int")
if not self._min <= value <= self._max:
raise ValueError(f"parameter value {value} not between " + \
f"{self._min} and {self._max}")
self._value = value
[docs]
class InputParameterFloat(InputParameter):
"""
InputParameterFloat defines a floating point input parameter with possible
lowest and highest values.
The `InputParameterFloat` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `float`. It also has the following
extra attributes:
Attributes
----------
_min: float
The lowest value (inclusive) that can be entered for this parameter.
_max: float
The highest value (inclusive) that can be entered for this parameter.
_format: str
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc.
"""
[docs]
def __init__(self, key: str, name: str, default_value: float,
display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False,
min_value:float=-math.inf, max_value:float=math.inf,
format_str:str="%.2f"):
"""
Create a new InputParameterFloat that can contain an float input
value for the simulation model.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: float
The default (initial) value of the parameter.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
min_value: float (optional)
The lowest value (inclusive) that can be entered for this
parameter.
max_value: float (optional)
The highest value (inclusive) that can be entered for this
parameter.
format_str: str (optional)
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc.
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a number
TypeError
when min_value or max_value is not a number
TypeError
when format_str is not a string
ValueError
when min_value >= max_value
ValueError
when default value not between min_value and max_value (inclusive)
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not (isinstance(default_value, float) or
isinstance(default_value, int)):
raise TypeError(f"default value {default_value} is not float/int")
if not isinstance(min_value, (int, float)):
raise TypeError(f"min value {min_value} is not an int or float")
if not isinstance(max_value, (int, float)):
raise TypeError(f"max value {max_value} is not an int or float")
if not isinstance(format_str, str):
raise TypeError(f"format string {format_str} is not a str")
if min_value >= max_value:
raise ValueError(f"min {min_value} >= max {max_value}")
if not min_value <= default_value <= max_value:
raise ValueError(f"default value {default_value} not between " + \
f"{min_value} and {max_value}")
self._min: float = min_value
self._max: float = max_value
self._format: str = format_str
@property
def value(self) -> float:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
float
The actual value of the parameter.
"""
return self._value
@property
def min_value(self) -> float:
"""
Returns the defined minimum allowed value (inclusive) of the parameter.
Returns
-------
float
The minimum allowed value of the parameter.
"""
return self._min
@property
def max_value(self) -> float:
"""
Returns the defined maximum allowed value (inclusive) of the parameter.
Returns
-------
float
The maximum allowed value of the parameter.
"""
return self._max
@property
def format_str(self) -> str:
"""
Returns the defined format string of the parameter value.
Returns
-------
str
The defined format string of the parameter value.
"""
return self._format
[docs]
def set_value(self, value: float):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: float
The new value of the parameter.
Raises
------
ValueError
if the parameter is read-only
TypeError
if the new value is not a number
ValueError
if the new value is not between the min_value and max_value
"""
if self.read_only:
raise ValueError(f"parameter {self.key} is read only")
if not isinstance(value, (float, int)):
raise TypeError(f"parameter value {value} not a number")
if not self._min <= value <= self._max:
raise ValueError(f"parameter value {value} not between " + \
f"{self._min} and {self._max}")
self._value = value
[docs]
class InputParameterStr(InputParameter):
"""
InputParameterStr defines a string input parameter.
The `InputParameterStr` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `str`.
"""
[docs]
def __init__(self, key: str, name: str, default_value: str,
display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False):
"""
Create a new InputParameterStr that can contain a string input
value for the simulation model.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: str
The default (initial) value of the parameter.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a string
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not isinstance(default_value, str):
raise TypeError(f"default value {default_value} is not a str")
@property
def value(self) -> str:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
str
The actual value of the parameter.
"""
return self._value
[docs]
def set_value(self, value: str):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: str
The new value of the parameter.
Raises
------
TypeError
if the new value is not a str
"""
if not isinstance(value, str):
raise ValueError(f"parameter value {value} not a str")
self._value = value
[docs]
class InputParameterBool(InputParameter):
"""
InputParameterBool defines a boolean input parameter.
The `InputParameterBool` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `bool`.
"""
[docs]
def __init__(self, key: str, name: str, default_value: bool,
display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False):
"""
Create a new InputParameterBool that can contain a boolean input
value for the simulation model.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: bool
The default (initial) value of the parameter.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a bool
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not isinstance(default_value, bool):
raise TypeError(f"default value {default_value} is not a bool")
@property
def value(self) -> bool:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
bool
The actual value of the parameter.
"""
return self._value
[docs]
def set_value(self, value: bool):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: bool
The new value of the parameter.
Raises
------
ValueError
if the parameter is read-only
TypeError
if the new value is not a boolean
"""
if self.read_only:
raise ValueError(f"parameter {self.key} is read only")
if not isinstance(value, bool):
raise TypeError(f"parameter value {value} not a bool")
self._value = value
[docs]
class InputParameterQuantity(InputParameter):
"""
InputParameterQuantity defines an input parameter that can contain a
quantity. For example, a Length, Speed or Duration can be entered
with the corresponding unit. Limits for lowest values and highest
allowed values (in the SI or base unit) can be provided for error
checking, e.g., to indicate that a value should be positive.
The `InputParameterQuantity` has all attributes of the `InputParameter`.
The `_value` attribute is of the type `Quantity`. It also has the
following extra attributes:
Attributes
----------
_min_si: float
The lowest value (inclusive) that can be entered for this parameter.
It is stored in the SI unit or base unit.
_max_si: float
The highest value (inclusive) that can be entered for this parameter.
It is stored in the SI unit or base unit.
_format: str
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc.
"""
[docs]
def __init__(self, key: str, name: str, default_value: Quantity,
display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False,
min_si:float=-math.inf, max_si:float=math.inf,
format_str:str="%.2f"):
"""
Create a new InputParameterQuantity that can contain an Quantity input
value for the simulation model. Examples of quantities are Length,
Frequency, Duration, etc.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
default_value: Quantity
The default (initial) value of the parameter.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
min_si: float (optional)
The lowest value (inclusive) that can be entered for this
parameter, specified in SI units or base units.
max_value: float (optional)
The highest value (inclusive) that can be entered for this
parameter, specified in SI units or base units.
format_str: str (optional)
The formatting string that is used in the user interface and when
printing the parameter, e.g. to limit the number of decimals,
to indicate the + or - sign, etc. The format string is used for
the numeric part only. The unit is added after the value, followed
by a space.
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a Quantity
TypeError
when min_si or max_si is not a number
TypeError
when format_str is not a string
ValueError
when min_value >= max_value
ValueError
when the default value, converted to SI units or base units, is
not between min_si and max_si (inclusive)
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not isinstance(default_value, Quantity):
raise TypeError(f"default value {default_value} is not a Quantity")
if not isinstance(min_si, (int, float)):
raise TypeError(f"min si value {min_si} is not an int or float")
if not isinstance(max_si, (int, float)):
raise TypeError(f"max si value {max_si} is not an int or float")
if not isinstance(format_str, str):
raise TypeError(f"format string {format_str} is not a str")
if min_si >= max_si:
raise ValueError(f"min SI {min_si} >= max SI {max_si}")
if not min_si <= default_value.si <= max_si:
raise ValueError(f"default value {default_value.si} not between " + \
f"{min_si} and {max_si}")
self._min_si: float = min_si
self._max_si: float = max_si
self._format: str = format_str
self._type: Type[Quantity] = type(default_value)
@property
def value(self) -> Quantity:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
Quantity
The actual value of the parameter.
"""
return self._value
@property
def min_si(self) -> float:
"""
Returns the defined minimum allowed value (inclusive) of the parameter.
It is stored in the SI unit or base unit.
Returns
-------
float
The minimum allowed value of the parameter in the SI or base unit.
"""
return self._min_si
@property
def max_si(self) -> float:
"""
Returns the defined maximum allowed value (inclusive) of the parameter.
It is stored in the SI unit or base unit.
Returns
-------
float
The maximum allowed value of the parameter in the SI or base unit.
"""
return self._max_si
@property
def format_str(self) -> str:
"""
Returns the defined format string of the parameter value.
Returns
-------
str
The defined format string of the parameter value.
"""
return self._format
@property
def type(self) -> Type[Quantity]:
"""
Returns the Quantity type of the parameter value (Length, Mass, etc.).
Returns
-------
type[Quantity]
The Quantity type of the parameter value.
"""
return self._type
[docs]
def set_value(self, value: Quantity):
"""
Set (overwrite) the actual value of the parameter. Use the correct
Quantity (Length, Speed, Mass, ..) for the parameter value.
Parameters
----------
value: Quantity
The new value of the parameter.
Raises
------
ValueError
if the parameter is read-only
TypeError
if the new value is not of the correct quantity type
ValueError
if the new value is not between the min and max si/base values
"""
if self.read_only:
raise ValueError("parameter {self.key} is read only")
if not isinstance(value, self._type):
raise ValueError(f"parameter value {value} not a " + \
f"{self._type.__name__}")
if not self._min_si <= value.si <= self._max_si:
raise ValueError(f"parameter SI value {value.si} not between " + \
f"{self._min_si} and {self._max_si}")
self._value = value
[docs]
class InputParameterSelectionList(InputParameter):
"""
InputParameterSelectionList defines a string input parameter that has
to be a member of a provided list of strings. In a user interface, this
can be indicated as a pick list. An example is a list of the state codes
of the USA.
The `InputParameterSelectionList` has all attributes of the
`InputParameter`. The `_value` attribute is of the type `str`.
It also has the following extra attributes:
Attributes
----------
_options: list[str]
The values that can be entered for this parameter.
"""
[docs]
def __init__(self, key: str, name: str, options: List[str],
default_value: str, display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False):
"""
Create a new InputParameterSelectionList that can contain a string
input value for the simulation model. The vaue of the string is
limited to the options in the provided selection list.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
options: list[str]
The list with values that can be entered for this parameter.
default_value: str
The default (initial) value of the parameter. This value has to
be a member of the options list.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a string
TypeError
when options is not a list
TypeError
when options contains entries that are not a string
ValueError
when default_value is not one of the options in the list
"""
super().__init__(key, name, default_value, display_priority,
parent=parent, description=description,
read_only=read_only)
if not isinstance(options, list):
raise TypeError(f"options {options} is not a list")
if not all([isinstance(x, str) for x in options]):
raise TypeError(f"non-str element(s) in options {options}")
if not isinstance(default_value, str):
raise TypeError(f"default value {default_value} not a str")
if not default_value in options:
raise ValueError(f"default value {default_value} not in options " \
+f"list {options}")
self._options = options
@property
def value(self) -> str:
"""
Returns the actual value of the parameter. The value is initialized
with default_value and is updated based on user input or data input.
Returns
-------
str
The actual value of the parameter, one of the elements of the list.
"""
return self._value
@property
def options(self) -> str:
"""
Returns the list of allowed values for the parameter.
Returns
-------
list[str]
The list with allowed values for the parameter.
"""
return self._options
[docs]
def set_value(self, value: str):
"""
Set (overwrite) the actual value of the parameter.
Parameters
----------
value: str
The new value of the parameter.
Raises
------
ValueError
if the parameter is read-only
TypeError
if the new value is not a string
ValueError
if the new value is not defined in the options list
"""
if self.read_only:
raise ValueError("parameter {self.key} is read only")
if not isinstance(value, str):
raise TypeError(f"parameter value {value} not a string")
if not value in self._options:
raise ValueError(f"value {value} is not a valid option " \
+f"from {self._options}")
self._value = value
[docs]
class InputParameterUnit(InputParameterSelectionList):
"""
InputParameterUnit defines an input parameter that is a unit for a
given quantity type. The `InputParameterUnit` class extends the
`InputParameterSelectionList` class and autogenerates a list of
units to select from.
The `InputParameterUnit` has all attributes of the
`InputParameterSelectionList`. The `_value` attribute is of the
type `str`.
"""
[docs]
def __init__(self, key: str, name: str, quantity: Type[Quantity],
default_value: str, display_priority: float, *,
parent: "InputParameterMap"=None, description: str=None,
read_only: bool=False):
"""
Create a new InputParameterSelectionList that can contain a string
input value for the simulation model. The vaue of the string is
limited to the options in the provided selection list.
Parameters
----------
key: str
The key of the parameter that can be a part of the
dot-notation to uniquely identify the model parameter. The key
does not contain the name of the parent, and should not contain
any periods. It should also be unique within its node of the
input parameter tree. The key is set at time of construction and
it is immutable.
name: str
Concise description of the input parameter, which can be used
in a GUI to identify the parameter to the user.
quantity: type[Quantity]
The Quantity class for which the unit selection list needs to
be generated.
default_value: str
The default (initial) value of the parameter. This value has to
be a member of the options list, so it has to be a unit of the
provided quantity.
display_priority: Union[int, float]
A number indicating the order of display of the parameter
in the parent parameter map. Floats are allowed to make it
easy to insert an extra parameter between parameters that
have already been allocated subsequent integer values.
parent: InputParameterMap (optional)
The parent map in which the parameter can be retrieved using its
key. Typically, only the root InputParameterMap has no parent,
and all other parameters have an InputParameterMap as parent.
description: str (optional)
A description or explanation of the InputParameter. For instance,
an indication of the bounds or the type. This value is purely
there for the user interface.
read_only: bool (optional)
Whether a user is prohibited from changing the value of the
parameter or not (default false, so the parameter *can* be
changed).
Raises
------
TypeError
when key is not a string
ValueError
when key is an empty string, or key contains a period
ValueError
when key is not unique in the parent InputParameterMap
TypeError
when name is not a string
ValueError
when name is an empty string
TypeError
when display priority is not a number
TypeError
when quantity is not a Quantity type / class
TypeError
when parent is not an InputParametermap or None
TypeError
when read_only is not a bool
TypeError
when default_value is not a string
ValueError
when default_value is not one of the units of the provided quantity
"""
if not issubclass(quantity, Quantity):
raise TypeError(f"quantity type {quantity} is not a Quantity")
if not default_value in quantity._units:
raise ValueError(f"default value {default_value} is not a unit " \
+f"for quantity {quantity}")
super().__init__(key, name, list(quantity._units.keys()),
default_value, display_priority, parent=parent,
description=description, read_only=read_only)
self._type: Type[Quantity] = quantity
@property
def unittype(self) -> Type[Quantity]:
"""
Returns the quantity type for which the units can be selected.
Returns
-------
type[Quantity]
The quantity type for which the units can be selected.
"""
return self._type