Skip to content

Commit c427340

Browse files
authored
Merge pull request #266 from dweindl/release_0.3.0
Release 0.3.0
2 parents 90379c4 + d8ad9b8 commit c427340

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+424
-305
lines changed

.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: 2
2+
updates:
3+
4+
- package-ecosystem: "github-actions"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
ignore:
9+
- dependency-name: "*"
10+
update-types: ["version-update:semver-patch", "version-update:semver-minor"]

.github/workflows/ci_tests.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: CI
22

33
on:
44
push:
5+
pull_request:
56
workflow_dispatch:
67
schedule:
78
- cron: '48 4 * * *'
@@ -11,7 +12,7 @@ jobs:
1112
strategy:
1213
matrix:
1314
platform: [windows-latest, macos-latest, ubuntu-latest]
14-
python-version: ["3.9", "3.11"]
15+
python-version: ["3.10", "3.12"]
1516
runs-on: ${{ matrix.platform }}
1617

1718
steps:

.pre-commit-config.yaml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
# See https://pre-commit.com for more information
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
4-
- repo: https://github.com/pycqa/isort
5-
rev: 5.12.0
6-
hooks:
7-
- id: isort
8-
name: isort (python)
9-
args: ["--profile", "black", "--filter-files", "--line-length", "79"]
104
- repo: https://github.com/pre-commit/pre-commit-hooks
115
rev: v4.4.0
126
hooks:
@@ -16,13 +10,19 @@ repos:
1610
args: [--allow-multiple-documents]
1711
- id: end-of-file-fixer
1812
- id: trailing-whitespace
19-
- repo: https://github.com/psf/black
20-
rev: 23.7.0
13+
- repo: https://github.com/astral-sh/ruff-pre-commit
14+
# Ruff version.
15+
rev: v0.1.11
2116
hooks:
22-
- id: black-jupyter
23-
# It is recommended to specify the latest version of Python
24-
# supported by your project here, or alternatively use
25-
# pre-commit's default_language_version, see
26-
# https://pre-commit.com/#top_level-default_language_version
27-
language_version: python3.11
28-
args: ["--line-length", "79"]
17+
# Run the linter.
18+
- id: ruff
19+
args:
20+
- --fix
21+
- --config
22+
- pyproject.toml
23+
24+
# Run the formatter.
25+
- id: ruff-format
26+
args:
27+
- --config
28+
- pyproject.toml

.readthedocs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ sphinx:
1010
build:
1111
os: "ubuntu-22.04"
1212
tools:
13-
python: "3.9"
13+
python: "3.10"
1414

1515
python:
1616
install:

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# PEtab changelog
22

3+
## 0.3 series
4+
5+
### 0.3.0
6+
7+
**This release requires `python>=3.10`**
8+
9+
**Features**
10+
* Visualization: Make line plot lines configurable via
11+
`petab.visualize.plotter.measurement_line_kwargs and
12+
`petab.visualize.plotter.simulation_line_kwargs`
13+
by @dweindl in https://github.com/PEtab-dev/libpetab-python/pull/254
14+
* Validator: check that `datasetId`s referenced in visualization tables exists
15+
in measurement tables
16+
by @dweindl in https://github.com/PEtab-dev/libpetab-python/pull/255
17+
18+
**Fixes**
19+
* Drop an index if it's reset
20+
by @dilpath in https://github.com/PEtab-dev/libpetab-python/pull/262
21+
22+
## New Contributors
23+
* @PaulJonasJost made their first contribution in https://github.com/PEtab-dev/libpetab-python/pull/250
24+
25+
**Full Changelog**: https://github.com/PEtab-dev/libpetab-python/compare/v0.2.9...v0.3.0
26+
327
## 0.2 series
428

529
### 0.2.9

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ and the easiest way to install it is running
2222

2323
pip3 install petab
2424

25-
It will require Python>=3.9 to run. (We are following the
25+
It will require Python>=3.10 to run. (We are following the
2626
[numpy Python support policy](https://numpy.org/neps/nep-0029-deprecation_policy.html)).
2727

2828
Development versions of the PEtab library can be installed using
@@ -57,7 +57,7 @@ Examples for PEtab Python library usage:
5757

5858
## Getting help
5959

60-
If you have any question or problems with this package, feel free to post them
60+
If you have any questions or problems with this package, feel free to post them
6161
at our GitHub [issue tracker](https://github.com/PEtab-dev/libpetab-python/issues/).
6262

6363
## Contributing

doc/conf.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# -- Project information -----------------------------------------------------
2121

2222
project = "libpetab-python"
23-
copyright = "2018-2023, the PEtab developers"
23+
copyright = "2018-2024, the PEtab developers"
2424
author = "PEtab developers"
2525

2626
# The full version, including alpha/beta/rc tags
@@ -29,7 +29,7 @@
2929
# -- Custom pre-build --------------------------------------------------------
3030

3131

32-
subprocess.run(["python", "md2rst.py"])
32+
subprocess.run([sys.executable, "md2rst.py"]) # noqa: S603
3333

3434
# -- General configuration ---------------------------------------------------
3535

@@ -74,7 +74,6 @@
7474
"members": None,
7575
"imported-members": ["petab"],
7676
"inherited-members": None,
77-
"private-members": None,
7877
"show-inheritance": None,
7978
}
8079

petab/calculate.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
import numpy as np
88
import pandas as pd
99
import sympy
10-
from sympy.abc import _clash
1110

1211
import petab
1312

1413
from .C import *
14+
from .math import sympify_petab
1515

1616
__all__ = [
1717
"calculate_residuals",
@@ -157,7 +157,7 @@ def get_symbolic_noise_formulas(observable_df) -> Dict[str, sympy.Expr]:
157157
if NOISE_FORMULA not in observable_df.columns:
158158
noise_formula = None
159159
else:
160-
noise_formula = sympy.sympify(row.noiseFormula, locals=_clash)
160+
noise_formula = sympify_petab(row.noiseFormula)
161161
noise_formulas[observable_id] = noise_formula
162162
return noise_formulas
163163

@@ -322,7 +322,8 @@ def calculate_llh_for_table(
322322
parameter_df: pd.DataFrame,
323323
) -> float:
324324
"""Calculate log-likelihood for one set of tables. For the arguments, see
325-
`calculate_llh`."""
325+
`calculate_llh`.
326+
"""
326327
llhs = []
327328

328329
# matching columns
@@ -335,7 +336,7 @@ def calculate_llh_for_table(
335336
noise_formulas = get_symbolic_noise_formulas(observable_df)
336337

337338
# iterate over measurements, find corresponding simulations
338-
for irow, row in measurement_df.iterrows():
339+
for _, row in measurement_df.iterrows():
339340
measurement = row[MEASUREMENT]
340341

341342
# look up in simulation df

petab/composite_problem.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def from_yaml(yaml_config: Union[Dict, str]) -> "CompositeProblem":
4646
Arguments:
4747
yaml_config: PEtab configuration as dictionary or YAML file name
4848
"""
49-
5049
if isinstance(yaml_config, str):
5150
path_prefix = os.path.dirname(yaml_config)
5251
yaml_config = yaml.load_yaml(yaml_config)

petab/conditions.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919

2020
def get_condition_df(
21-
condition_file: Union[str, pd.DataFrame, Path, None]
21+
condition_file: Union[str, pd.DataFrame, Path, None],
2222
) -> pd.DataFrame:
2323
"""Read the provided condition file into a ``pandas.Dataframe``
2424
@@ -40,14 +40,17 @@ def get_condition_df(
4040
)
4141

4242
if not isinstance(condition_file.index, pd.RangeIndex):
43-
condition_file.reset_index(inplace=True)
43+
condition_file.reset_index(
44+
drop=condition_file.index.name != CONDITION_ID,
45+
inplace=True,
46+
)
4447

4548
try:
4649
condition_file.set_index([CONDITION_ID], inplace=True)
4750
except KeyError:
4851
raise KeyError(
4952
f"Condition table missing mandatory field {CONDITION_ID}."
50-
)
53+
) from None
5154

5255
return condition_file
5356

@@ -75,7 +78,6 @@ def create_condition_df(
7578
A :py:class:`pandas.DataFrame` with empty given rows and columns and
7679
all nan values
7780
"""
78-
7981
condition_ids = [] if condition_ids is None else list(condition_ids)
8082

8183
data = {CONDITION_ID: condition_ids}

petab/core.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def write_simulation_df(df: pd.DataFrame, filename: Union[str, Path]) -> None:
7272

7373

7474
def get_visualization_df(
75-
visualization_file: Union[str, Path, pd.DataFrame, None]
75+
visualization_file: Union[str, Path, pd.DataFrame, None],
7676
) -> Union[pd.DataFrame, None]:
7777
"""Read PEtab visualization table
7878
@@ -102,7 +102,8 @@ def get_visualization_df(
102102
except pd.errors.EmptyDataError:
103103
warn(
104104
"Visualization table is empty. Defaults will be used. "
105-
"Refer to the documentation for details."
105+
"Refer to the documentation for details.",
106+
stacklevel=2,
106107
)
107108
vis_spec = pd.DataFrame()
108109
return vis_spec
@@ -226,9 +227,9 @@ def get_flattened_id_mappings(
226227

227228
mappings[OBSERVABLE_ID][observable_replacement_id] = observable_id
228229

229-
for field, hyperparameter_type, target in [
230-
(NOISE_PARAMETERS, "noiseParameter", NOISE_FORMULA),
231-
(OBSERVABLE_PARAMETERS, "observableParameter", OBSERVABLE_FORMULA),
230+
for field, hyperparameter_type in [
231+
(NOISE_PARAMETERS, "noiseParameter"),
232+
(OBSERVABLE_PARAMETERS, "observableParameter"),
232233
]:
233234
if field in measurements:
234235
mappings[field][
@@ -357,7 +358,6 @@ def concat_tables(
357358
Returns:
358359
The concatenated DataFrames
359360
"""
360-
361361
if isinstance(tables, pd.DataFrame):
362362
return tables
363363

@@ -389,7 +389,6 @@ def to_float_if_float(x: Any) -> Any:
389389
Returns:
390390
``x`` as float if possible, otherwise ``x``
391391
"""
392-
393392
try:
394393
return float(x)
395394
except (ValueError, TypeError):
@@ -427,19 +426,18 @@ def create_combine_archive(
427426
email: E-mail address of archive creator
428427
organization: Organization of archive creator
429428
"""
430-
431429
path_prefix = os.path.dirname(str(yaml_file))
432430
yaml_config = yaml.load_yaml(yaml_file)
433431

434432
# function-level import, because module-level import interfered with
435433
# other SWIG interfaces
436434
try:
437435
import libcombine
438-
except ImportError:
436+
except ImportError as err:
439437
raise ImportError(
440438
"To use PEtab's COMBINE functionality, libcombine "
441439
"(python-libcombine) must be installed."
442-
)
440+
) from err
443441

444442
def _add_file_metadata(location: str, description: str = ""):
445443
"""Add metadata to the added file"""

petab/lint.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
import numpy as np
1111
import pandas as pd
1212
import sympy as sp
13-
from sympy.abc import _clash
1413

1514
import petab
1615

1716
from . import core, measurements, parameters
1817
from .C import * # noqa: F403
18+
from .math import sympify_petab
1919
from .models import Model
2020

2121
logger = logging.getLogger(__name__)
@@ -105,7 +105,6 @@ def check_condition_df(
105105
Raises:
106106
AssertionError: in case of problems
107107
"""
108-
109108
# Check required columns are present
110109
req_cols = []
111110
_check_df(df, req_cols, "condition")
@@ -167,7 +166,6 @@ def check_measurement_df(
167166
Raises:
168167
AssertionError, ValueError: in case of problems
169168
"""
170-
171169
_check_df(df, MEASUREMENT_DF_REQUIRED_COLS, "measurement")
172170

173171
for column_name in MEASUREMENT_DF_REQUIRED_COLS:
@@ -319,7 +317,7 @@ def check_observable_df(observable_df: pd.DataFrame) -> None:
319317
for row in observable_df.itertuples():
320318
obs = getattr(row, OBSERVABLE_FORMULA)
321319
try:
322-
sp.sympify(obs, locals=_clash)
320+
sympify_petab(obs)
323321
except sp.SympifyError as e:
324322
raise AssertionError(
325323
f"Cannot parse expression '{obs}' "
@@ -328,7 +326,7 @@ def check_observable_df(observable_df: pd.DataFrame) -> None:
328326

329327
noise = getattr(row, NOISE_FORMULA)
330328
try:
331-
sympified_noise = sp.sympify(noise, locals=_clash)
329+
sympified_noise = sympify_petab(noise)
332330
if sympified_noise is None or (
333331
sympified_noise.is_Number and not sympified_noise.is_finite
334332
):
@@ -432,7 +430,6 @@ def assert_measured_observables_defined(
432430
Raises:
433431
AssertionError: in case of problems
434432
"""
435-
436433
used_observables = set(measurement_df[OBSERVABLE_ID].values)
437434
defined_observables = set(observable_df.index.values)
438435
if undefined_observables := (used_observables - defined_observables):
@@ -453,7 +450,6 @@ def condition_table_is_parameter_free(condition_df: pd.DataFrame) -> bool:
453450
``True`` if there are no parameter overrides in the condition table,
454451
``False`` otherwise.
455452
"""
456-
457453
return len(petab.get_parametric_overrides(condition_df)) == 0
458454

459455

@@ -468,7 +464,6 @@ def assert_parameter_id_is_string(parameter_df: pd.DataFrame) -> None:
468464
Raises:
469465
AssertionError: in case of problems
470466
"""
471-
472467
for parameter_id in parameter_df:
473468
if isinstance(parameter_id, str):
474469
if parameter_id[0].isdigit():
@@ -1088,7 +1083,6 @@ def assert_measurement_conditions_present_in_condition_table(
10881083
Raises:
10891084
AssertionError: in case of problems
10901085
"""
1091-
10921086
used_conditions = set(measurement_df[SIMULATION_CONDITION_ID].values)
10931087
if PREEQUILIBRATION_CONDITION_ID in measurement_df:
10941088
used_conditions |= set(

0 commit comments

Comments
 (0)