Skip to content

Commit f263174

Browse files
authored
Release 0.1.11
Merge pull request #475 from PEtab-dev/release_0.1.11 * Functions for generating synthetic data (#472) * Minor documentation updates (#470)
2 parents ac82baf + fa1578e commit f263174

File tree

9 files changed

+406
-2
lines changed

9 files changed

+406
-2
lines changed

.github/workflows/ci_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: CI
22

33
# trigger
4-
on: [push]
4+
on: [push, workflow_dispatch]
55

66
jobs:
77
build:

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## 0.1 series
44

5+
### 0.1.11
6+
7+
* Function for generating synthetic data (#472)
8+
* Minor documentation updates (#470)
9+
510
### 0.1.10
611

712
*Fixed deployment setup, no further changes.*

doc/example.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ The following examples should help to get a better idea of how to use the PEtab
1010

1111
example/example_petablint.ipynb
1212
example/example_visualization.ipynb
13+
14+
Examples of systems biology parameter estimation problems specified in PEtab
15+
can be found in the `systems biology benchmark model collection <https://github.com/Benchmarking-Initiative/Benchmark-Models-PEtab>`_.

doc/how_to_cite.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.. _how_to_cite:
2+
3+
How to cite
4+
===========
5+
6+
Help us to promote PEtab: When using PEtab, please cite our `preprint <https://arxiv.org/abs/2004.01154v4>`_:
7+
8+
.. code-block:: latex
9+
10+
@misc{schmiester2020petab,
11+
title={PEtab -- interoperable specification of parameter estimation problems in systems biology},
12+
author={Leonard Schmiester and Yannik Schälte and Frank T. Bergmann and Tacio Camba and Erika Dudkin and Janine Egert and Fabian Fröhlich and Lara Fuhrmann and Adrian L. Hauber and Svenja Kemmer and Polina Lakrisenko and Carolin Loos and Simon Merkt and Wolfgang Müller and Dilan Pathirana and Elba Raimúndez and Lukas Refisch and Marcus Rosenblatt and Paul L. Stapor and Philipp Städter and Dantong Wang and Franz-Georg Wieland and Julio R. Banga and Jens Timmer and Alejandro F. Villaverde and Sven Sahle and Clemens Kreutz and Jan Hasenauer and Daniel Weindl},
13+
year={2020},
14+
eprint={2004.01154},
15+
archivePrefix={arXiv},
16+
primaryClass={q-bio.QM}
17+
}

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
:caption: About
1919

2020
Changelog <CHANGELOG.md>
21+
how_to_cite
2122
license
2223
logo/LICENSE.md
2324

petab/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .problem import * # noqa: F403, F401, E402
2222
from .sampling import * # noqa: F403, F401, E402
2323
from .sbml import * # noqa: F403, F401, E402
24+
from .simulate import * # noqa: F403, F401, E402
2425
from .yaml import * # noqa: F403, F401, E402
2526
from .version import __version__ # noqa: F401, E402
2627
from .format_version import __format_version__ # noqa: F401, E402

petab/simulate.py

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import abc
2+
import numpy as np
3+
import pathlib
4+
import pandas as pd
5+
import petab
6+
import shutil
7+
import sympy as sp
8+
import tempfile
9+
from typing import Dict, Optional, Union
10+
11+
12+
class Simulator(abc.ABC):
13+
"""
14+
Base class that specific simulators should inherit.
15+
Specific simulators should minimally implement the
16+
`simulate_without_noise` method.
17+
Example (AMICI): https://bit.ly/33SUSG4
18+
19+
Attributes:
20+
noise_formulas:
21+
The formulae that will be used to calculate the scale of noise
22+
distributions.
23+
petab_problem:
24+
A PEtab problem, which will be simulated.
25+
rng:
26+
A NumPy random generator, used to sample from noise distributions.
27+
temporary_working_dir:
28+
Whether `working_dir` is a temporary directory, which can be
29+
deleted without significant consequence.
30+
working_dir:
31+
All simulator-specific output files will be saved here. This
32+
directory and its contents may be modified and deleted, and
33+
should be considered ephemeral.
34+
"""
35+
def __init__(self,
36+
petab_problem: petab.Problem,
37+
working_dir: Optional[Union[pathlib.Path, str]] = None):
38+
"""
39+
Initialize the simulator with sufficient information to perform a
40+
simulation. If no working directory is specified, a temporary one is
41+
created.
42+
43+
Arguments:
44+
petab_problem:
45+
A PEtab problem.
46+
working_dir:
47+
All simulator-specific output files will be saved here. This
48+
directory and its contents may be modified and deleted, and
49+
should be considered ephemeral.
50+
"""
51+
self.petab_problem = petab_problem
52+
53+
self.temporary_working_dir = False
54+
if working_dir is None:
55+
working_dir = tempfile.mkdtemp()
56+
self.temporary_working_dir = True
57+
if not isinstance(working_dir, pathlib.Path):
58+
working_dir = pathlib.Path(working_dir)
59+
self.working_dir = working_dir
60+
self.working_dir.mkdir(parents=True, exist_ok=True)
61+
62+
self.noise_formulas = petab.calculate.get_symbolic_noise_formulas(
63+
self.petab_problem.observable_df)
64+
self.rng = np.random.default_rng()
65+
66+
def remove_working_dir(self, force: bool = False, **kwargs) -> None:
67+
"""
68+
Remove the simulator working directory and all files within (see the
69+
`__init__` method arguments).
70+
71+
Arguments:
72+
force:
73+
If True, the working directory is removed regardless of
74+
whether it is a temporary directory.
75+
"""
76+
if force or self.temporary_working_dir:
77+
shutil.rmtree(self.working_dir, **kwargs)
78+
if self.working_dir.is_dir():
79+
print('Failed to remove the working directory: '
80+
+ str(self.working_dir))
81+
else:
82+
print('By default, specified working directories are not removed. '
83+
'Please call this method with `force=True`, or manually '
84+
f'delete the working directory: {self.working_dir}')
85+
86+
@abc.abstractmethod
87+
def simulate_without_noise(self) -> pd.DataFrame:
88+
"""
89+
Simulate a PEtab problem. This is an abstract method that should be
90+
implemented in a simulation package. Links to examples of this are in
91+
the class docstring.
92+
93+
Returns:
94+
Simulated data, as a PEtab measurements table, which should be
95+
equivalent to replacing all values in the `petab.C.MEASUREMENT`
96+
column of the measurements table (of the PEtab problem supplied to
97+
the `__init__` method), with simulated values.
98+
"""
99+
100+
def simulate(
101+
self,
102+
noise: bool = False,
103+
noise_scaling_factor: float = 1,
104+
**kwargs
105+
) -> pd.DataFrame:
106+
"""Simulate a PEtab problem, optionally with noise.
107+
108+
Arguments:
109+
noise: If True, noise is added to simulated data.
110+
noise_scaling_factor:
111+
A multiplier of the scale of the noise distribution.
112+
113+
Returns:
114+
Simulated data, as a PEtab measurements table.
115+
"""
116+
simulation_df = self.simulate_without_noise(**kwargs)
117+
if noise:
118+
simulation_df = self.add_noise(simulation_df, noise_scaling_factor)
119+
return simulation_df
120+
121+
def add_noise(
122+
self,
123+
simulation_df: pd.DataFrame,
124+
noise_scaling_factor: float = 1,
125+
) -> pd.DataFrame:
126+
"""Add noise to simulated data.
127+
128+
Arguments:
129+
simulation_df:
130+
A PEtab measurements table that contains simulated data.
131+
noise_scaling_factor:
132+
A multiplier of the scale of the noise distribution.
133+
134+
Returns:
135+
Simulated data with noise, as a PEtab measurements table.
136+
"""
137+
simulation_df_with_noise = simulation_df.copy()
138+
simulation_df_with_noise[petab.C.MEASUREMENT] = [
139+
sample_noise(
140+
self.petab_problem,
141+
row,
142+
row[petab.C.MEASUREMENT],
143+
self.noise_formulas,
144+
self.rng,
145+
noise_scaling_factor,
146+
)
147+
for _, row in simulation_df_with_noise.iterrows()
148+
]
149+
return simulation_df_with_noise
150+
151+
152+
def sample_noise(
153+
petab_problem: petab.Problem,
154+
measurement_row: pd.Series,
155+
simulated_value: float,
156+
noise_formulas: Optional[Dict[str, sp.Expr]] = None,
157+
rng: Optional[np.random.Generator] = None,
158+
noise_scaling_factor: float = 1,
159+
) -> float:
160+
"""Generate a sample from a PEtab noise distribution.
161+
162+
Arguments:
163+
petab_problem:
164+
The PEtab problem used to generate the simulated value.
165+
Instance of `petab.Problem`.
166+
measurement_row:
167+
The row in the PEtab problem measurement table that corresponds
168+
to the simulated value.
169+
simulated_value:
170+
A simulated value without noise.
171+
noise_formulas:
172+
Processed noise formulas from the PEtab observables table, in the
173+
form output by the `petab.calculate.get_symbolic_noise_formulas`
174+
method.
175+
rng:
176+
A NumPy random generator.
177+
noise_scaling_factor:
178+
A multiplier of the scale of the noise distribution.
179+
180+
Returns:
181+
The sample from the PEtab noise distribution.
182+
"""
183+
if noise_formulas is None:
184+
noise_formulas = petab.calculate.get_symbolic_noise_formulas(
185+
petab_problem.observable_df)
186+
if rng is None:
187+
rng = np.random.default_rng()
188+
189+
noise_value = petab.calculate.evaluate_noise_formula(
190+
measurement_row,
191+
noise_formulas,
192+
petab_problem.parameter_df,
193+
simulated_value
194+
)
195+
196+
# default noise distribution is petab.C.NORMAL
197+
noise_distribution = (
198+
petab_problem
199+
.observable_df
200+
.loc[measurement_row[petab.C.OBSERVABLE_ID]]
201+
.get(petab.C.NOISE_DISTRIBUTION, petab.C.NORMAL)
202+
)
203+
204+
# below is e.g.: `np.random.normal(loc=simulation, scale=noise_value)`
205+
return getattr(rng, noise_distribution)(
206+
loc=simulated_value,
207+
scale=noise_value * noise_scaling_factor
208+
)

petab/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""PEtab library version"""
2-
__version__ = '0.1.10'
2+
__version__ = '0.1.11'

0 commit comments

Comments
 (0)