|
33 | 33 | "\n", |
34 | 34 | "from petab.v1.C import *\n", |
35 | 35 | "from petab.v1.priors import Prior\n", |
| 36 | + "from petab.v1.parameters import scale, unscale\n", |
| 37 | + "\n", |
36 | 38 | "\n", |
37 | 39 | "sns.set_style(None)\n", |
38 | 40 | "\n", |
39 | 41 | "\n", |
40 | | - "def plot(prior: Prior, ax=None):\n", |
| 42 | + "def plot(prior: Prior):\n", |
41 | 43 | " \"\"\"Visualize a distribution.\"\"\"\n", |
| 44 | + " fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))\n", |
| 45 | + " sample = prior.sample(20_000, x_scaled=True)\n", |
| 46 | + "\n", |
| 47 | + " fig.suptitle(str(prior))\n", |
| 48 | + "\n", |
| 49 | + " plot_single(prior, ax=ax1, sample=sample, scaled=False)\n", |
| 50 | + " plot_single(prior, ax=ax2, sample=sample, scaled=True)\n", |
| 51 | + " plt.tight_layout()\n", |
| 52 | + " plt.show()\n", |
| 53 | + "\n", |
| 54 | + "def plot_single(prior: Prior, scaled: bool = False, ax=None, sample: np.array = None):\n", |
| 55 | + " fig = None\n", |
42 | 56 | " if ax is None:\n", |
43 | 57 | " fig, ax = plt.subplots()\n", |
44 | 58 | "\n", |
45 | | - " sample = prior.sample(20_000)\n", |
| 59 | + " if sample is None:\n", |
| 60 | + " sample = prior.sample(20_000)\n", |
| 61 | + "\n", |
| 62 | + " # assuming scaled sample\n", |
| 63 | + " if not scaled:\n", |
| 64 | + " sample = unscale(sample, prior.transformation)\n", |
| 65 | + " bounds = prior.bounds\n", |
| 66 | + " else:\n", |
| 67 | + " bounds = (prior.lb_scaled, prior.ub_scaled) if prior.bounds is not None else None\n", |
46 | 68 | "\n", |
47 | | - " # pdf\n", |
48 | | - " xmin = min(sample.min(), prior.lb_scaled if prior.bounds is not None else sample.min())\n", |
49 | | - " xmax = max(sample.max(), prior.ub_scaled if prior.bounds is not None else sample.max())\n", |
| 69 | + " # plot pdf\n", |
| 70 | + " xmin = min(sample.min(), bounds[0] if prior.bounds is not None else sample.min())\n", |
| 71 | + " xmax = max(sample.max(), bounds[1] if prior.bounds is not None else sample.max())\n", |
50 | 72 | " padding = 0.1 * (xmax - xmin)\n", |
51 | 73 | " xmin -= padding\n", |
52 | 74 | " xmax += padding\n", |
53 | 75 | " x = np.linspace(xmin, xmax, 500)\n", |
54 | | - " y = prior.pdf(x)\n", |
| 76 | + " y = prior.pdf(x, x_scaled=scaled, rescale=scaled)\n", |
55 | 77 | " ax.plot(x, y, color='red', label='pdf')\n", |
56 | 78 | "\n", |
57 | 79 | " sns.histplot(sample, stat='density', ax=ax, label=\"sample\")\n", |
58 | 80 | "\n", |
59 | | - " # bounds\n", |
| 81 | + " # plot bounds\n", |
60 | 82 | " if prior.bounds is not None:\n", |
61 | | - " for bound in (prior.lb_scaled, prior.ub_scaled):\n", |
| 83 | + " for bound in bounds:\n", |
62 | 84 | " if bound is not None and np.isfinite(bound):\n", |
63 | 85 | " ax.axvline(bound, color='black', linestyle='--', label='bound')\n", |
64 | 86 | "\n", |
65 | | - " ax.set_title(str(prior))\n", |
66 | | - " ax.set_xlabel('Parameter value on the parameter scale')\n", |
| 87 | + " if fig is not None:\n", |
| 88 | + " ax.set_title(str(prior))\n", |
| 89 | + "\n", |
| 90 | + " if scaled:\n", |
| 91 | + " ax.set_xlabel(f'Parameter value on parameter scale ({prior.transformation})')\n", |
| 92 | + " ax.set_ylabel(\"Rescaled density\")\n", |
| 93 | + " else:\n", |
| 94 | + " ax.set_xlabel('Parameter value')\n", |
| 95 | + "\n", |
67 | 96 | " ax.grid(False)\n", |
68 | 97 | " handles, labels = ax.get_legend_handles_labels()\n", |
69 | 98 | " unique_labels = dict(zip(labels, handles))\n", |
70 | 99 | " ax.legend(unique_labels.values(), unique_labels.keys())\n", |
71 | | - " plt.show()" |
| 100 | + "\n", |
| 101 | + " if ax is None:\n", |
| 102 | + " plt.show()\n" |
72 | 103 | ], |
73 | 104 | "id": "initial_id", |
74 | 105 | "outputs": [], |
|
84 | 115 | "metadata": {}, |
85 | 116 | "cell_type": "code", |
86 | 117 | "source": [ |
87 | | - "plot(Prior(UNIFORM, (0, 1)))\n", |
88 | | - "plot(Prior(NORMAL, (0, 1)))\n", |
89 | | - "plot(Prior(LAPLACE, (0, 1)))\n", |
90 | | - "plot(Prior(LOG_NORMAL, (0, 1)))\n", |
91 | | - "plot(Prior(LOG_LAPLACE, (1, 0.5)))" |
| 118 | + "plot_single(Prior(UNIFORM, (0, 1)))\n", |
| 119 | + "plot_single(Prior(NORMAL, (0, 1)))\n", |
| 120 | + "plot_single(Prior(LAPLACE, (0, 1)))\n", |
| 121 | + "plot_single(Prior(LOG_NORMAL, (0, 1)))\n", |
| 122 | + "plot_single(Prior(LOG_LAPLACE, (1, 0.5)))" |
92 | 123 | ], |
93 | 124 | "id": "4f09e50a3db06d9f", |
94 | 125 | "outputs": [], |
|
97 | 128 | { |
98 | 129 | "metadata": {}, |
99 | 130 | "cell_type": "markdown", |
100 | | - "source": "If a parameter scale is specified (`parameterScale=lin|log|log10` not a `parameterScale*`-type distribution), the sample is transformed accordingly (but not the distribution parameters):\n", |
| 131 | + "source": "If a parameter scale is specified (`parameterScale=lin|log|log10`) and the chosen distribution is not a `parameterScale*`-type distribution, then the distribution parameters are taken as is, i.e., the `parameterScale` is not applied to the distribution parameters. In the context of PEtab prior distributions, `parameterScale` will only be used for the start point sampling for optimization, where the sample will be transformed accordingly. This is demonstrated below. The left plot always shows the prior distribution for unscaled parameter values, and the right plot shows the prior distribution for scaled parameter values. Note that in the objective function, the prior is always on the unscaled parameters.\n", |
101 | 132 | "id": "dab4b2d1e0f312d8" |
102 | 133 | }, |
103 | 134 | { |
|
134 | 165 | { |
135 | 166 | "metadata": {}, |
136 | 167 | "cell_type": "markdown", |
137 | | - "source": "Prior distributions can also be defined on the parameter scale by using the types `parameterScaleUniform`, `parameterScaleNormal` or `parameterScaleLaplace`. In these cases, 1) the distribution parameter are interpreted on the transformed parameter scale, and 2) a sample from the given distribution is used directly, without applying any transformation according to `parameterScale` (this implies, that for `parameterScale=lin`, there is no difference between `parameterScaleUniform` and `uniform`):", |
| 168 | + "source": "Prior distributions can also be defined on the scaled parameters (i.e., transformed according to `parameterScale`) by using the types `parameterScaleUniform`, `parameterScaleNormal` or `parameterScaleLaplace`. In these cases, the distribution parameter are interpreted on the transformed parameter scale (but not the parameter bounds, see below). This implies, that for `parameterScale=lin`, there is no difference between `parameterScaleUniform` and `uniform`.", |
138 | 169 | "id": "263c9fd31156a4d5" |
139 | 170 | }, |
140 | 171 | { |
|
167 | 198 | "plot(Prior(UNIFORM, (0, 1), bounds=(0.1, 0.9)))\n", |
168 | 199 | "plot(Prior(UNIFORM, (1e-8, 1), bounds=(0.1, 0.9), transformation=LOG10))\n", |
169 | 200 | "plot(Prior(LAPLACE, (0, 1), bounds=(-0.5, 0.5)))\n", |
170 | | - "plot(Prior(PARAMETER_SCALE_UNIFORM, (-3, 1), bounds=(1e-2, 1), transformation=LOG10))\n" |
| 201 | + "plot(Prior(PARAMETER_SCALE_UNIFORM, (-3, 1), bounds=(1e-2, 1), transformation=LOG10))" |
171 | 202 | ], |
172 | 203 | "id": "4ac42b1eed759bdd", |
173 | 204 | "outputs": [], |
|
184 | 215 | "cell_type": "code", |
185 | 216 | "source": [ |
186 | 217 | "plot(Prior(NORMAL, (10, 1), bounds=(6, 11), transformation=\"log10\"))\n", |
187 | | - "plot(Prior(PARAMETER_SCALE_NORMAL, (10, 1), bounds=(10**9, 10**14), transformation=\"log10\"))\n", |
| 218 | + "plot(Prior(PARAMETER_SCALE_NORMAL, (2, 1), bounds=(10**0, 10**3), transformation=\"log10\"))\n", |
188 | 219 | "plot(Prior(LAPLACE, (10, 2), bounds=(6, 14)))\n", |
189 | 220 | "plot(Prior(LOG_LAPLACE, (1, 0.5), bounds=(0.5, 8)))\n", |
190 | 221 | "plot(Prior(LOG_NORMAL, (2, 1), bounds=(0.5, 8)))" |
|
0 commit comments