Skip to content

Commit

Permalink
updating optimization result plots
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiaskoenig committed Jun 24, 2024
1 parent e5d2f70 commit 77ba1d7
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 58 deletions.
118 changes: 61 additions & 57 deletions src/sbmlsim/fit/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib.figure import Axes, Figure
from matplotlib.figure import Figure
from matplotlib.axes import Axes
from matplotlib.lines import Line2D
from sbmlutils import log

Expand Down Expand Up @@ -151,28 +152,21 @@ def run(self, mpl_parameters: Dict[str, Any] = None) -> None:
parameters.update(mpl_parameters)
plt.rcParams.update(parameters)


# optimization traces
self.plot_traces(
path=plots_dir / f"traces.{self.image_format}",
)
# waterfall plot
if self.optres.size > 1:
self.plot_waterfall(
path=plots_dir / f"waterfall.{self.image_format}",
)
# optimization traces
self.plot_traces(
path=plots_dir / f"traces.{self.image_format}",
)

# plot fit results for optimal parameters
if self.op:
xopt = self.optres.xopt

self.plot_cost_scatter(
x=xopt,
path=plots_dir / f"cost_scatter.{self.image_format}",
)
self.plot_cost_bar(
x=xopt,
path=plots_dir / f"cost_bar.{self.image_format}",
)
self.plot_datapoint_scatter(
x=xopt,
path=plots_dir / f"datapoint_scatter.{self.image_format}",
Expand All @@ -181,6 +175,16 @@ def run(self, mpl_parameters: Dict[str, Any] = None) -> None:
x=xopt,
path=plots_dir / f"residual_scatter.{self.image_format}",
)

self.plot_cost_scatter(
x=xopt,
path=plots_dir / f"cost_scatter.{self.image_format}",
)
self.plot_cost_bar(
x=xopt,
path=plots_dir / f"cost_bar.{self.image_format}",
)

self.plot_residual_boxplot(
x=xopt,
path=plots_dir / f"residual_boxplot.{self.image_format}",
Expand Down Expand Up @@ -292,11 +296,11 @@ def html_report(self, path: Path):
f_out.write(html)

def _create_mpl_figure(
self, width: float = 5.0, height: float = 5.0
self, width: float = 5.0, height: float = 5.0, layout: str = "constrained"
) -> Tuple[Figure, Axes]:
"""Create matplotlib figure."""
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(width, height))
fig.subplots_adjust(left=0.2, bottom=0.1)
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(width, height), layout=layout)
# fig.subplots_adjust(left=0.2, bottom=0.1)

return fig, ax

Expand Down Expand Up @@ -559,55 +563,57 @@ def _datapoints_df(self, x: np.ndarray) -> pd.DataFrame:
],
)


kwargs_scatter = {
"markersize": "10",
"markeredgecolor": "black",
"alpha": 0.7,
"linestyle": "",
"marker": "o",
}

@timeit
def plot_datapoint_scatter(self, x: np.ndarray, path: Path):
"""Plot cost scatter plot.
Compares cost of model parameters to the given parameter set.
"""
fig, ax = self._create_mpl_figure()

dp: pd.DataFrame = self._datapoints_df(x=x)

# FIXME: plot error bars
# plot lines
min_dp = np.nanmin([np.nanmin(dp.y_ref), np.nanmin(dp.y_obs)]) * 0.1
max_dp = np.nanmax([np.nanmax(dp.y_ref), np.nanmax(dp.y_obs)]) * 10

ax.fill_between(
[min_dp, max_dp, max_dp, min_dp],
[min_dp/10, max_dp/10, max_dp*10, min_dp*10],
color="lightgray",
)
ax.plot([min_dp, max_dp], [min_dp, max_dp], color="black")
for bfactor in [1/10, 10]:
ax.plot(
[min_dp, max_dp],
[min_dp * bfactor, max_dp * bfactor],
"--",
color="black",
)

# plot data
for experiment in sorted(dp.experiment.unique()):
ax.plot(
dp.y_ref[dp.experiment == experiment].values,
dp.y_obs[dp.experiment == experiment].values,
# yerr=dp.y_ref_err,
linestyle="",
marker="o",
# label="model",
# color="black",
markersize="10",
alpha=0.9,
**self.kwargs_scatter
)

min_dp = np.min(
[
np.min(dp.y_ref),
np.min(dp.y_obs),
]
)
max_dp = np.max(
[
np.max(dp.y_ref),
np.max(dp.y_obs),
]
)

ax.plot(
[min_dp * 0.5, max_dp * 2],
[min_dp * 0.5, max_dp * 2],
"--",
color="black",
)

# annotations
for k in range(len(dp)):

if (
np.abs(dp.y_ref.values[k] - dp.y_obs.values[k]) / dp.y_ref.values[k]
> 0.5
):
# plot labels for datapoints far away
ratio = dp.y_ref.values[k]/dp.y_obs.values[k]
if (ratio > 10 or ratio < 1/10):
ax.annotate(
dp.experiment.values[k],
xy=(
Expand All @@ -616,11 +622,13 @@ def plot_datapoint_scatter(self, x: np.ndarray, path: Path):
),
fontsize="x-small",
alpha=0.9,
# textcoords="offset fontsize"
)
ax.set_xlabel("Experiment $y_{i,k}$")
ax.set_ylabel("Prediction $f(x_{i,k})$")
ax.set_xlabel("Experiment $y_{i,k}$", fontweight="bold")
ax.set_ylabel("Prediction $f(x_{i,k})$", fontweight="bold")
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlim(min_dp, max_dp)
ax.grid()
if self.show_titles:
ax.set_title("Data points")
Expand All @@ -639,11 +647,7 @@ def plot_residual_scatter(self, x: np.ndarray, path: Path):
ax.plot(
xdata[dp.experiment == experiment].values,
ydata[dp.experiment == experiment].values,
linestyle="",
marker="o",
# color="black",
markersize="10",
alpha=0.9,
**self.kwargs_scatter
)

min_res = np.min(ydata)
Expand Down Expand Up @@ -685,8 +689,8 @@ def plot_residual_scatter(self, x: np.ndarray, path: Path):
fontsize="x-small",
alpha=0.7,
)
ax.set_xlabel("Experiment $y_{i,k}$")
ax.set_ylabel("Relative residual $\\frac{f(x_{i,k})-y_{i,k}}{y_{i,k}}$")
ax.set_xlabel("Experiment $y_{i,k}$", fontweight="bold")
ax.set_ylabel("Relative residual $\\frac{f(x_{i,k})-y_{i,k}}{y_{i,k}}$", fontweight="bold")
ax.set_xscale("log")
# ax.set_yscale("log")
ax.grid()
Expand Down
2 changes: 1 addition & 1 deletion src/sbmlsim/fit/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def __init__(
else:
uuid_str = str(uuid.uuid4())
self.sid = (
"{:%Y%m%d_%H%M%S}".format(datetime.datetime.now()) + f"__{uuid_str}"
"{:%Y%m%d_%H%M%S}".format(datetime.datetime.now()) + f"__{uuid_str[:5]}"
)
self.parameters: List[FitParameter] = []
for p in parameters:
Expand Down

0 comments on commit 77ba1d7

Please sign in to comment.