Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serveral refactorings in glotaran.Parameter #910

Merged
merged 18 commits into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ad18248
Added Parameter to and from dict methods.
joernweissenborn Nov 20, 2021
0064f88
Moved markdown related parameter group tests to test_parameter_group_…
joernweissenborn Nov 20, 2021
4cc77d2
Refactored parameter tests.
joernweissenborn Nov 20, 2021
a76ad61
Added parameter to and from dictonionary list.
joernweissenborn Nov 20, 2021
02f5a9e
Added more extensive test for paramater csv.
joernweissenborn Nov 20, 2021
f6f5026
Added `as_optimized` to parameter(group) as dict and dataframe functi…
joernweissenborn Nov 21, 2021
95aac8c
Fixed deprecation test.
joernweissenborn Nov 21, 2021
ef65e56
Added `Parameter.markdown`
joernweissenborn Nov 21, 2021
5e2d1e2
Update glotaran/parameter/parameter_group.py
joernweissenborn Nov 21, 2021
0d10f4b
♻️ Refactored by Sourcery (less if nesting)
Nov 21, 2021
36123af
🩹 Fixed renamed method get_group_for_parameter_by_label only in def
s-weigand Nov 21, 2021
bed48e8
🧹 Removed redunent int since mypy sees int as subclass of float
s-weigand Nov 21, 2021
9d5ea14
♻️ Changed stderr type from 'float|None' to float and default to np.nan
s-weigand Nov 21, 2021
9402e55
🩹🧪 Fixed tests due to changed rendering
s-weigand Nov 21, 2021
5172afa
👌 Improved typing where dict and list were used w/o types
s-weigand Nov 21, 2021
053e356
🧹👌 Fixed up left over tying issues in parameters
s-weigand Nov 21, 2021
6c418bb
🧹 Fixed typo
s-weigand Nov 21, 2021
4168edd
🧹 Apply minor naming suggestions from code review
s-weigand Nov 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@
from glotaran.examples.sequential import parameter


def test_parameter_group_to_csv(tmp_path: Path):
def test_parameter_group_to_csv_no_stderr(tmp_path: Path):
"""``ParameterGroup.to_csv`` raises deprecation warning and saves file."""
parameter_path = tmp_path / "test_parameter.csv"
deprecation_warning_on_call_test_helper(
parameter.to_csv, args=[parameter_path.as_posix()], raise_exception=True
)
expected = dedent(
"""\
label,value,minimum,maximum,vary,non-negative,expression
j.1,1.0,-inf,inf,False,False,None
j.0,0.0,-inf,inf,False,False,None
kinetic.1,0.5,-inf,inf,True,False,None
kinetic.2,0.3,-inf,inf,True,False,None
kinetic.3,0.1,-inf,inf,True,False,None
irf.center,0.3,-inf,inf,True,False,None
irf.width,0.1,-inf,inf,True,False,None
label,value,expression,minimum,maximum,non-negative,vary,standard-error
j.1,1.0,None,-inf,inf,False,False,None
j.0,0.0,None,-inf,inf,False,False,None
kinetic.1,0.5,None,-inf,inf,False,True,None
kinetic.2,0.3,None,-inf,inf,False,True,None
kinetic.3,0.1,None,-inf,inf,False,True,None
irf.center,0.3,None,-inf,inf,False,True,None
irf.width,0.1,None,-inf,inf,False,True,None
"""
)

Expand Down
10 changes: 5 additions & 5 deletions glotaran/model/test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,9 @@ def test_model_markdown():
* **k1**:
* *Label*: k1
* *Matrix*:
* *('s2', 's1')*: rates.1: **5.01000e-01** *(StdErr: 0e+00)*
* *('s3', 's2')*: rates.2: **2.02000e-02** *(StdErr: 0e+00)*
* *('s3', 's3')*: rates.3: **1.05000e-03** *(StdErr: 0e+00)*
* *('s2', 's1')*: rates.1: **5.01000e-01** *(StdErr: nan)*
* *('s3', 's2')*: rates.2: **2.02000e-02** *(StdErr: nan)*
* *('s3', 's3')*: rates.3: **1.05000e-03** *(StdErr: nan)*


## Initial Concentration
Expand All @@ -532,8 +532,8 @@ def test_model_markdown():
* **irf1** (multi-gaussian):
* *Label*: irf1
* *Type*: multi-gaussian
* *Center*: [irf.center: **1.30000e+00** *(StdErr: 0e+00)*]
* *Width*: [irf.width: **7.80000e+00** *(StdErr: 0e+00)*]
* *Center*: [irf.center: **1.30000e+00** *(StdErr: nan)*]
* *Width*: [irf.width: **7.80000e+00** *(StdErr: nan)*]
* *Normalize*: True
* *Backsweep*: False

Expand Down
113 changes: 105 additions & 8 deletions glotaran/parameter/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import numpy as np
from numpy.typing._array_like import _SupportsArray

from glotaran.utils.ipython import MarkdownStr
from glotaran.utils.sanitize import sanitize_parameter_list

if TYPE_CHECKING:
Expand Down Expand Up @@ -42,11 +43,12 @@ def __init__(
self,
label: str = None,
full_label: str = None,
expression: str = None,
maximum: int | float = np.inf,
minimum: int | float = -np.inf,
expression: str | None = None,
s-weigand marked this conversation as resolved.
Show resolved Hide resolved
maximum: float = np.inf,
minimum: float = -np.inf,
non_negative: bool = False,
value: float | int = np.nan,
standard_error: float = np.nan,
value: float = np.nan,
vary: bool = True,
):
"""Optimization Parameter supporting numpy array operations.
Expand All @@ -58,15 +60,17 @@ def __init__(
full_label : str
The label of the parameter with its path in a parameter group prepended.
, by default None
expression : str
expression : str | None
Expression to calculate the parameters value from,
e.g. if used in relation to another parameter. , by default None
maximum : int
maximum : float
Upper boundary for the parameter to be varied to., by default np.inf
minimum : int
minimum : float
Lower boundary for the parameter to be varied to., by default -np.inf
non_negative : bool
Whether the parameter should always be bigger than zero., by default False
standard_error: float
The standard error of the parameter. , by default ``np.nan``
value : float
Value of the parameter, by default np.nan
vary : bool
Expand All @@ -79,7 +83,7 @@ def __init__(
self.maximum = maximum
self.minimum = minimum
self.non_negative = non_negative
self.standard_error = 0.0
self.standard_error = standard_error
self.value = value
self.vary = vary

Expand Down Expand Up @@ -144,6 +148,55 @@ def from_list_or_value(
param._set_options_from_dict(options)
return param

@classmethod
def from_dict(cls, parameter_dict: dict[str, Parameter]) -> Parameter:
jsnel marked this conversation as resolved.
Show resolved Hide resolved
"""Create a :class:`Parameter` from a dictionary.

Expects a dictionary created by :method:`Parameter.as_dict`.

Parameters
----------
parameter_dict : dict
The source dictionary.

Returns
-------
Parameter
The created :class:`Parameter`
"""
parameter_dict = {k.replace("-", "_"): v for k, v in parameter_dict.items()}
parameter_dict["full_label"] = parameter_dict["label"]
parameter_dict["label"] = parameter_dict["label"].split(".")[-1]
return cls(**parameter_dict)

def as_dict(self, as_optimized: bool = True) -> dict:
jsnel marked this conversation as resolved.
Show resolved Hide resolved
"""Create a dictionary containing the parameter properties.

Intended for internal use.
s-weigand marked this conversation as resolved.
Show resolved Hide resolved

Parameters
----------
as_optimized : bool
Whether to include properties which are the result of optimization.

Returns
-------
dict
The created dictionary.
"""
parameter_dict = {
"label": self.full_label,
"value": self.value,
"expression": self.expression,
"minimum": self.minimum,
"maximum": self.maximum,
"non-negative": self.non_negative,
"vary": self.vary,
}
if as_optimized:
parameter_dict["standard-error"] = self.standard_error
return parameter_dict

def set_from_group(self, group: ParameterGroup):
"""Set all values of the parameter to the values of the corresponding parameter in the group.

Expand Down Expand Up @@ -409,6 +462,50 @@ def set_value_from_optimization(self, value: float):
"""
self.value = np.exp(value) if self.non_negative else value

def markdown(
jsnel marked this conversation as resolved.
Show resolved Hide resolved
self,
all_parameter: ParameterGroup | None = None,
initial_parameter: ParameterGroup | None = None,
) -> MarkdownStr:
"""Get a markdown representation of the parameter.

Parameters
----------
all_parameter : ParameterGroup | None
A parameter group containing the whole parameter set (used for expression lookup).
initial_parameter : ParameterGroup | None
The initial parameter.

Returns
-------
MarkdownStr
The parameter as markdown string.
"""
md = f"{self.full_label}"

value = f"{self.value:.2e}"
if self.vary:
if self.standard_error is not np.nan:
value += f"±{self.standard_error}"
if initial_parameter is not None:
initial_value = initial_parameter.get(self.full_label).value
value += f", initial: {initial_value:.2e}"
md += f"({value})"
elif self.expression is not None:
expression = self.expression
if all_parameter is not None:
for match in PARAMETER_EXPRESION_REGEX.findall(expression):
label = match[0]
parameter = all_parameter.get(label)
expression = expression.replace(
"$" + label, f"_{parameter.markdown(all_parameter=all_parameter)}_"
)
md += f"({value}={expression})"
else:
md += f"({value}, fixed)"

return MarkdownStr(md)

def __getstate__(self):
"""Get state for pickle."""
return (
Expand Down
Loading