Skip to content

Commit 3ebb0be

Browse files
dweindldilpath
andauthored
Various cleanup (#163)
* Fix typehints * Documentation formatting cross-referencing * Formatting * ... Co-authored-by: Dilan Pathirana <59329744+dilpath@users.noreply.github.com>
1 parent 9a092bc commit 3ebb0be

File tree

13 files changed

+193
-175
lines changed

13 files changed

+193
-175
lines changed

petab/conditions.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ def get_parametric_overrides(condition_df: pd.DataFrame) -> List[str]:
9393
Returns:
9494
List of parameter IDs that are mapped in a condition-specific way
9595
"""
96-
constant_parameters = list(
97-
set(condition_df.columns.values.tolist()) - {CONDITION_ID,
98-
CONDITION_NAME})
96+
constant_parameters = (set(condition_df.columns.values.tolist())
97+
- {CONDITION_ID, CONDITION_NAME})
9998
result = []
10099

101100
for column in constant_parameters:
@@ -104,7 +103,5 @@ def get_parametric_overrides(condition_df: pd.DataFrame) -> List[str]:
104103

105104
floatified = condition_df.loc[:, column].apply(core.to_float_if_float)
106105

107-
for x in floatified:
108-
if not isinstance(x, float):
109-
result.append(x)
106+
result.extend(x for x in floatified if not isinstance(x, float))
110107
return result

petab/core.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ def get_notnull_columns(df: pd.DataFrame, candidates: Iterable):
9191

9292

9393
def flatten_timepoint_specific_output_overrides(
94-
petab_problem: 'petab.problem.Problem') -> None:
94+
petab_problem: 'petab.problem.Problem',
95+
) -> None:
9596
"""Flatten timepoint-specific output parameter overrides.
9697
9798
If the PEtab problem definition has timepoint-specific

petab/lint.py

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ def _check_df(df: pd.DataFrame, req_cols: Iterable, name: str) -> None:
6060
Raises:
6161
AssertionError: if a column is missing
6262
"""
63-
cols_set = df.columns.values
64-
missing_cols = set(req_cols) - set(cols_set)
65-
if missing_cols:
63+
if missing_cols := set(req_cols) - set(df.columns.values):
6664
raise AssertionError(
6765
f"DataFrame {name} requires the columns {missing_cols}.")
6866

@@ -105,7 +103,7 @@ def check_condition_df(
105103
_check_df(df, req_cols, "condition")
106104

107105
# Check for correct index
108-
if not df.index.name == CONDITION_ID:
106+
if df.index.name != CONDITION_ID:
109107
raise AssertionError(
110108
f"Condition table has wrong index {df.index.name}."
111109
f"expected {CONDITION_ID}.")
@@ -161,14 +159,9 @@ def check_measurement_df(df: pd.DataFrame,
161159
df[column_name].values, column_name)
162160

163161
if observable_df is not None:
164-
# Check all observables are defined
165-
observables_defined = set(observable_df.index.values)
166-
observables_used = set(df[OBSERVABLE_ID])
167-
observables_undefined = observables_used - observables_defined
168-
if observables_undefined:
169-
raise ValueError(f"Observables {observables_undefined} used in "
170-
"measurement table but not defined in "
171-
"observables table.")
162+
assert_measured_observables_defined(df, observable_df)
163+
measurements.assert_overrides_match_parameter_count(
164+
df, observable_df)
172165

173166
if OBSERVABLE_TRANSFORMATION in observable_df:
174167
# Check for positivity of measurements in case of
@@ -183,11 +176,6 @@ def check_measurement_df(df: pd.DataFrame,
183176
f'transformation {trafo} must be '
184177
f'positive, but {measurement} <= 0.')
185178

186-
if observable_df is not None:
187-
assert_measured_observables_defined(df, observable_df)
188-
measurements.assert_overrides_match_parameter_count(
189-
df, observable_df)
190-
191179
assert_measurements_not_null(df)
192180
assert_measurements_numeric(df)
193181

@@ -213,7 +201,7 @@ def check_parameter_df(
213201

214202
_check_df(df, PARAMETER_DF_REQUIRED_COLS[1:], "parameter")
215203

216-
if not df.index.name == PARAMETER_ID:
204+
if df.index.name != PARAMETER_ID:
217205
raise AssertionError(
218206
f"Parameter table has wrong index {df.index.name}."
219207
f"expected {PARAMETER_ID}.")
@@ -239,10 +227,11 @@ def check_parameter_df(
239227
f"but column {NOMINAL_VALUE} is missing.")
240228
try:
241229
df.loc[non_estimated_par_ids, NOMINAL_VALUE].apply(float)
242-
except ValueError:
243-
raise AssertionError("Expected numeric values for "
244-
f"`{NOMINAL_VALUE}` in parameter table for "
245-
"all non-estimated parameters.")
230+
except ValueError as e:
231+
raise AssertionError(
232+
f"Expected numeric values for `{NOMINAL_VALUE}` in parameter "
233+
"table for all non-estimated parameters."
234+
) from e
246235

247236
assert_parameter_id_is_string(df)
248237
assert_parameter_scale_is_valid(df)
@@ -292,8 +281,9 @@ def check_observable_df(observable_df: pd.DataFrame) -> None:
292281
try:
293282
sp.sympify(obs)
294283
except sp.SympifyError as e:
295-
raise AssertionError(f"Cannot parse expression '{obs}' "
296-
f"for observable {row.Index}: {e}")
284+
raise AssertionError(
285+
f"Cannot parse expression '{obs}' "
286+
f"for observable {row.Index}: {e}") from e
297287

298288
noise = getattr(row, NOISE_FORMULA)
299289
try:
@@ -304,9 +294,10 @@ def check_observable_df(observable_df: pd.DataFrame) -> None:
304294
raise AssertionError(f"No or non-finite {NOISE_FORMULA} "
305295
f"given for observable {row.Index}.")
306296
except sp.SympifyError as e:
307-
raise AssertionError(f"Cannot parse expression '{noise}' "
308-
f"for noise model for observable "
309-
f"{row.Index}: {e}")
297+
raise AssertionError(
298+
f"Cannot parse expression '{noise}' "
299+
f"for noise model for observable " f"{row.Index}: {e}"
300+
) from e
310301

311302

312303
def assert_all_parameters_present_in_parameter_df(
@@ -353,7 +344,8 @@ def assert_all_parameters_present_in_parameter_df(
353344

354345
def assert_measured_observables_defined(
355346
measurement_df: pd.DataFrame,
356-
observable_df: pd.DataFrame) -> None:
347+
observable_df: pd.DataFrame
348+
) -> None:
357349
"""Check if all observables in the measurement table have been defined in
358350
the observable table
359351
@@ -367,12 +359,11 @@ def assert_measured_observables_defined(
367359

368360
used_observables = set(measurement_df[OBSERVABLE_ID].values)
369361
defined_observables = set(observable_df.index.values)
370-
undefined_observables = used_observables - defined_observables
371-
372-
if undefined_observables:
362+
if undefined_observables := (used_observables - defined_observables):
373363
raise AssertionError(
374-
"Undefined observables in measurement file: "
375-
f"{undefined_observables}.")
364+
f"Observables {undefined_observables} used in "
365+
"measurement table but not defined in observables table."
366+
)
376367

377368

378369
def condition_table_is_parameter_free(condition_df: pd.DataFrame) -> bool:
@@ -547,9 +538,10 @@ def assert_parameter_prior_parameters_are_valid(
547538
pars = tuple(
548539
float(val) for val in pars_str.split(PARAMETER_SEPARATOR)
549540
)
550-
except ValueError:
541+
except ValueError as e:
551542
raise AssertionError(
552-
f"Could not parse prior parameters '{pars_str}'.")
543+
f"Could not parse prior parameters '{pars_str}'.") from e
544+
553545
# all distributions take 2 parameters
554546
if len(pars) != 2:
555547
raise AssertionError(
@@ -933,9 +925,7 @@ def assert_measurement_conditions_present_in_condition_table(
933925
used_conditions |= \
934926
set(measurement_df[PREEQUILIBRATION_CONDITION_ID].dropna().values)
935927
available_conditions = set(condition_df.index.values)
936-
missing_conditions = used_conditions - available_conditions
937-
938-
if missing_conditions:
928+
if missing_conditions := (used_conditions - available_conditions):
939929
raise AssertionError("Measurement table references conditions that "
940930
"are not specified in the condition table: "
941931
+ str(missing_conditions))

petab/measurements.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# noqa: F405
33

44
import itertools
5+
import math
56
import numbers
67
from pathlib import Path
78
from typing import Dict, List, Union
@@ -201,7 +202,7 @@ def create_measurement_df() -> pd.DataFrame:
201202
Created DataFrame
202203
"""
203204

204-
df = pd.DataFrame(data={
205+
return pd.DataFrame(data={
205206
OBSERVABLE_ID: [],
206207
PREEQUILIBRATION_CONDITION_ID: [],
207208
SIMULATION_CONDITION_ID: [],
@@ -213,8 +214,6 @@ def create_measurement_df() -> pd.DataFrame:
213214
REPLICATE_ID: []
214215
})
215216

216-
return df
217-
218217

219218
def measurements_have_replicates(measurement_df: pd.DataFrame) -> bool:
220219
"""Tests whether the measurements come with replicates
@@ -235,15 +234,15 @@ def measurements_have_replicates(measurement_df: pd.DataFrame) -> bool:
235234

236235
def assert_overrides_match_parameter_count(
237236
measurement_df: pd.DataFrame,
238-
observable_df: pd.DataFrame) -> None:
237+
observable_df: pd.DataFrame
238+
) -> None:
239239
"""Ensure that number of parameters in the observable definition matches
240240
the number of overrides in ``measurement_df``
241241
242242
Arguments:
243243
measurement_df: PEtab measurement table
244244
observable_df: PEtab observable table
245245
"""
246-
247246
# sympify only once and save number of parameters
248247
observable_parameters_count = {
249248
obs_id: len(observables.get_formula_placeholders(
@@ -260,10 +259,11 @@ def assert_overrides_match_parameter_count(
260259
# check observable parameters
261260
try:
262261
expected = observable_parameters_count[row[OBSERVABLE_ID]]
263-
except KeyError:
262+
except KeyError as e:
264263
raise ValueError(
265264
f"Observable {row[OBSERVABLE_ID]} used in measurement table "
266-
f"is not defined.")
265+
f"is not defined.") from e
266+
267267
actual = len(split_parameter_replacement_list(
268268
row.get(OBSERVABLE_PARAMETERS, None)))
269269
# No overrides are also allowed
@@ -289,7 +289,7 @@ def assert_overrides_match_parameter_count(
289289
except KeyError:
290290
# no overrides defined, but a numerical sigma can be provided
291291
# anyways
292-
if not len(replacements) == 1 \
292+
if len(replacements) != 1 \
293293
or not isinstance(replacements[0], numbers.Number):
294294
raise AssertionError(
295295
f'No placeholders have been specified in the noise model '

petab/observables.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import re
44
from collections import OrderedDict
55
from pathlib import Path
6-
from typing import List, Union
6+
from typing import List, Union, Literal
77

88
import pandas as pd
99
import sympy as sp
@@ -105,17 +105,20 @@ def get_output_parameters(
105105
return list(output_parameters.keys())
106106

107107

108-
def get_formula_placeholders(formula_string: str, observable_id: str,
109-
override_type: str) -> List[str]:
108+
def get_formula_placeholders(
109+
formula_string: str,
110+
observable_id: str,
111+
override_type: Literal['observable', 'noise'],
112+
) -> List[str]:
110113
"""
111114
Get placeholder variables in noise or observable definition for the
112115
given observable ID.
113116
114117
Arguments:
115118
formula_string: observable formula
116119
observable_id: ID of current observable
117-
override_type: 'observable' or 'noise', depending on whether `formula`
118-
is for observable or for noise model
120+
override_type: ``'observable'`` or ``'noise'``, depending on whether
121+
``formula`` is for observable or for noise model
119122
120123
Returns:
121124
List of placeholder parameter IDs in the order expected in the
@@ -192,6 +195,4 @@ def create_observable_df() -> pd.DataFrame:
192195
Created DataFrame
193196
"""
194197

195-
df = pd.DataFrame(data={col: [] for col in OBSERVABLE_DF_COLS})
196-
197-
return df
198+
return pd.DataFrame(data={col: [] for col in OBSERVABLE_DF_COLS})

0 commit comments

Comments
 (0)