Skip to content

Commit 9967ce1

Browse files
authored
Fix use of multiple parameter files (#156)
* check for duplicate parameter definitions Testing: * duplicate parameterId to always raise an error * check for parameters with only unique parameterId
1 parent 5a87f83 commit 9967ce1

File tree

2 files changed

+60
-19
lines changed

2 files changed

+60
-19
lines changed

petab/parameters.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,8 @@ def get_parameter_df(
5555
return None
5656

5757
parameter_df = pd.concat(dfs)
58-
# Remove identical parameter definitions
59-
parameter_df.drop_duplicates(inplace=True, ignore_index=False)
6058
# Check for contradicting parameter definitions
61-
parameter_duplicates = set(parameter_df.index.values[
62-
parameter_df.index.duplicated()])
63-
if parameter_duplicates:
64-
raise ValueError(
65-
f'The values of {PARAMETER_ID} must be unique or'
66-
' identical between all parameter subset files. The'
67-
' following duplicates were found:\n'
68-
f'{parameter_duplicates}'
69-
)
59+
_check_for_contradicting_parameter_definitions(parameter_df)
7060

7161
return parameter_df
7262

@@ -81,10 +71,24 @@ def get_parameter_df(
8171
except KeyError as e:
8272
raise KeyError(
8373
f"Parameter table missing mandatory field {PARAMETER_ID}.") from e
74+
_check_for_contradicting_parameter_definitions(parameter_df)
8475

8576
return parameter_df
8677

8778

79+
def _check_for_contradicting_parameter_definitions(parameter_df: pd.DataFrame):
80+
"""
81+
Raises a ValueError for non-unique parameter IDs
82+
"""
83+
parameter_duplicates = set(parameter_df.index.values[
84+
parameter_df.index.duplicated()])
85+
if parameter_duplicates:
86+
raise ValueError(
87+
f'The values of `{PARAMETER_ID}` must be unique. The '
88+
f'following duplicates were found:\n{parameter_duplicates}'
89+
)
90+
91+
8892
def write_parameter_df(df: pd.DataFrame, filename: Union[str, Path]) -> None:
8993
"""Write PEtab parameter table
9094

tests/test_parameters.py

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ def test_get_parameter_df():
8181
PARAMETER_ID: ['id3'],
8282
PARAMETER_NAME: ['name3']
8383
})
84-
parameter_dfs['subset2_overlap'] = pd.DataFrame(data={
84+
parameter_dfs['subset2_redundance'] = pd.DataFrame(data={
8585
PARAMETER_ID: ['id2', 'id3'],
8686
PARAMETER_NAME: ['name2', 'name3']
8787
})
88-
parameter_dfs['subset2_error'] = pd.DataFrame(data={
88+
parameter_dfs['subset2_contradiction'] = pd.DataFrame(data={
8989
PARAMETER_ID: ['id2', 'id3'],
9090
PARAMETER_NAME: ['different_name2', 'name3']
9191
})
@@ -98,15 +98,52 @@ def test_get_parameter_df():
9898
assert(petab.get_parameter_df(parameter_files['complete']).equals(
9999
petab.get_parameter_df([parameter_files['subset1'],
100100
parameter_files['subset2_strict']])))
101-
# Check that identical parameter definitions are correctly combined
102-
assert(petab.get_parameter_df(parameter_files['complete']).equals(
103-
petab.get_parameter_df([parameter_files['subset1'],
104-
parameter_files['subset2_overlap']])))
105101
# Ensure an error is raised if there exist parameterId duplicates
102+
# with identical parameter definitions
103+
with pytest.raises(ValueError):
104+
petab.get_parameter_df(
105+
[parameter_files["subset1"],
106+
parameter_files["subset2_redundance"]]
107+
)
106108
# with non-identical parameter definitions
107109
with pytest.raises(ValueError):
108-
petab.get_parameter_df([parameter_files['subset1'],
109-
parameter_files['subset2_error']])
110+
petab.get_parameter_df(
111+
[parameter_files["subset1"],
112+
parameter_files["subset2_contradiction"],
113+
]
114+
)
115+
116+
# Ensure that parameters that differ only by parameterId
117+
# are recognized as distinct
118+
with tempfile.TemporaryDirectory() as directory:
119+
parameter_dfs, parameter_files = ({}, {})
120+
parameter_dfs["complete"] = pd.DataFrame(
121+
data={
122+
PARAMETER_ID: ["id1", "id2", "id3", "id4"],
123+
NOMINAL_VALUE: [1, 1, 1, 1],
124+
}
125+
)
126+
parameter_dfs["subset1"] = pd.DataFrame(
127+
data={PARAMETER_ID: ["id1", "id2"], NOMINAL_VALUE: [1, 1]}
128+
)
129+
parameter_dfs["subset2"] = pd.DataFrame(
130+
data={PARAMETER_ID: ["id3", "id4"], NOMINAL_VALUE: [1, 1]}
131+
)
132+
for name, df in parameter_dfs.items():
133+
with tempfile.NamedTemporaryFile(
134+
mode="w", delete=False, dir=directory
135+
) as fh:
136+
parameter_files[name] = fh.name
137+
parameter_dfs[name].to_csv(fh, sep="\t", index=False)
138+
# from one parameter file
139+
df_template = parameter_dfs["complete"].set_index(PARAMETER_ID)
140+
df_test = petab.get_parameter_df(parameter_files["complete"])
141+
assert (df_template == df_test).all().all()
142+
# several parameter files
143+
assert petab.get_parameter_df(parameter_files["complete"]).equals(
144+
petab.get_parameter_df([parameter_files["subset1"],
145+
parameter_files["subset2"]])
146+
)
110147

111148

112149
def test_write_parameter_df():

0 commit comments

Comments
 (0)