Skip to content

Commit 653cafd

Browse files
committed
Fix experiment table in upconversion
1 parent f4a79eb commit 653cafd

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

petab/v2/lint.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,16 @@ class CheckValidPetabIdColumn(ValidationTask):
228228
"""A task to check that a given column contains only valid PEtab IDs."""
229229

230230
def __init__(
231-
self, table_name: str, column_name: str, required_column: bool = True
231+
self,
232+
table_name: str,
233+
column_name: str,
234+
required_column: bool = True,
235+
ignore_nan: bool = False,
232236
):
233237
self.table_name = table_name
234238
self.column_name = column_name
235239
self.required_column = required_column
240+
self.ignore_nan = ignore_nan
236241

237242
def run(self, problem: Problem) -> ValidationIssue | None:
238243
df = getattr(problem, f"{self.table_name}_df")
@@ -248,7 +253,10 @@ def run(self, problem: Problem) -> ValidationIssue | None:
248253
return
249254

250255
try:
251-
check_ids(df[self.column_name].values, kind=self.column_name)
256+
ids = df[self.column_name].values
257+
if self.ignore_nan:
258+
ids = ids[~pd.isna(ids)]
259+
check_ids(ids, kind=self.column_name)
252260
except ValueError as e:
253261
return ValidationError(str(e))
254262

@@ -318,6 +326,13 @@ def run(self, problem: Problem) -> ValidationIssue | None:
318326
return
319327

320328
used_experiments = set(problem.measurement_df[EXPERIMENT_ID].values)
329+
# handle default-experiment
330+
used_experiments = set(
331+
filter(
332+
lambda x: not isinstance(x, float) or not np.isnan(x),
333+
used_experiments,
334+
)
335+
)
321336
available_experiments = set(
322337
problem.experiment_df[EXPERIMENT_ID].unique()
323338
)
@@ -826,7 +841,7 @@ def append_overrides(overrides):
826841
CheckMeasurementTable(),
827842
CheckConditionTable(),
828843
CheckExperimentTable(),
829-
CheckValidPetabIdColumn("experiment", EXPERIMENT_ID),
844+
CheckValidPetabIdColumn("experiment", EXPERIMENT_ID, ignore_nan=True),
830845
CheckValidPetabIdColumn("experiment", CONDITION_ID),
831846
CheckExperimentConditionsExist(),
832847
CheckObservableTable(),

petab/v2/petab1to2.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ def petab1to2(yaml_config: Path | str, output_dir: Path | str = None):
6363
if get_major_version(yaml_config) != 1:
6464
raise ValueError("PEtab problem is not version 1.")
6565
petab_problem = ProblemV1.from_yaml(yaml_file or yaml_config)
66+
# get rid of conditionName column if present (unsupported in v2)
67+
petab_problem.condition_df = petab_problem.condition_df.drop(
68+
columns=[v1.C.CONDITION_NAME], errors="ignore"
69+
)
6670
if v1.lint_problem(petab_problem):
6771
raise ValueError("Provided PEtab problem does not pass linting.")
6872

@@ -72,8 +76,6 @@ def petab1to2(yaml_config: Path | str, output_dir: Path | str = None):
7276
# Write new YAML file
7377
output_dir = Path(output_dir)
7478
output_dir.mkdir(parents=True, exist_ok=True)
75-
new_yaml_file = output_dir / Path(yaml_file).name
76-
write_yaml(new_yaml_config, new_yaml_file)
7779

7880
# Update tables
7981
# condition tables, observable tables, SBML files, parameter table:
@@ -104,6 +106,19 @@ def petab1to2(yaml_config: Path | str, output_dir: Path | str = None):
104106
def create_experiment_id(sim_cond_id: str, preeq_cond_id: str) -> str:
105107
if not sim_cond_id and not preeq_cond_id:
106108
return ""
109+
# check whether the conditions will exist in the v2 condition table
110+
sim_cond_exists = (
111+
petab_problem.condition_df.loc[sim_cond_id].notna().any()
112+
)
113+
preeq_cond_exists = (
114+
preeq_cond_id
115+
and petab_problem.condition_df.loc[preeq_cond_id].notna().any()
116+
)
117+
if not sim_cond_exists and not preeq_cond_exists:
118+
# if we have only all-NaN conditions, we don't create a new
119+
# experiment
120+
return ""
121+
107122
if preeq_cond_id:
108123
preeq_cond_id = f"{preeq_cond_id}_"
109124
exp_id = f"experiment__{preeq_cond_id}__{sim_cond_id}"
@@ -126,6 +141,8 @@ def create_experiment_id(sim_cond_id: str, preeq_cond_id: str) -> str:
126141
sim_cond_id = row[v1.C.SIMULATION_CONDITION_ID]
127142
preeq_cond_id = row.get(v1.C.PREEQUILIBRATION_CONDITION_ID, "")
128143
exp_id = create_experiment_id(sim_cond_id, preeq_cond_id)
144+
if not exp_id:
145+
continue
129146
if preeq_cond_id:
130147
experiments.append(
131148
{
@@ -167,8 +184,8 @@ def create_experiment_id(sim_cond_id: str, preeq_cond_id: str) -> str:
167184
if v1.C.PREEQUILIBRATION_CONDITION_ID in measurement_df.columns:
168185
measurement_df[
169186
v1.C.PREEQUILIBRATION_CONDITION_ID
170-
] = measurement_df[v1.C.PREEQUILIBRATION_CONDITION_ID].astype(
171-
str
187+
] = measurement_df[v1.C.PREEQUILIBRATION_CONDITION_ID].fillna(
188+
""
172189
)
173190
else:
174191
measurement_df[v1.C.PREEQUILIBRATION_CONDITION_ID] = ""
@@ -209,6 +226,9 @@ def create_experiment_id(sim_cond_id: str, preeq_cond_id: str) -> str:
209226
measurement_df, get_dest_path(measurement_file)
210227
)
211228

229+
new_yaml_file = output_dir / Path(yaml_file).name
230+
write_yaml(new_yaml_config, new_yaml_file)
231+
212232
# validate updated Problem
213233
validation_issues = v2.lint_problem(new_yaml_file)
214234

0 commit comments

Comments
 (0)