@@ -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
@@ -308,21 +316,26 @@ def run(self, problem: Problem) -> ValidationIssue | None:
308316 except AssertionError as e :
309317 return ValidationError (str (e ))
310318
311- # TODO: introduce some option for validation partial vs full
319+ # TODO: introduce some option for validation of partial vs full
312320 # problem. if this is supposed to be a complete problem, a missing
313321 # condition table should be an error if the measurement table refers
314- # to conditions
315-
316- # check that measured experiments
317- if problem .experiment_df is None :
318- return
319-
322+ # to conditions, otherwise it should maximally be a warning
320323 used_experiments = set (problem .measurement_df [EXPERIMENT_ID ].values )
321- available_experiments = set (
322- problem .experiment_df [EXPERIMENT_ID ].unique ()
324+ # handle default-experiment
325+ used_experiments = set (
326+ filter (
327+ lambda x : not isinstance (x , float ) or not np .isnan (x ),
328+ used_experiments ,
329+ )
330+ )
331+ # check that measured experiments exist
332+ available_experiments = (
333+ set (problem .experiment_df [EXPERIMENT_ID ].unique ())
334+ if problem .experiment_df is not None
335+ else set ()
323336 )
324337 if missing_experiments := (used_experiments - available_experiments ):
325- raise AssertionError (
338+ return ValidationError (
326339 "Measurement table references experiments that "
327340 "are not specified in the experiments table: "
328341 + str (missing_experiments )
@@ -826,7 +839,7 @@ def append_overrides(overrides):
826839 CheckMeasurementTable (),
827840 CheckConditionTable (),
828841 CheckExperimentTable (),
829- CheckValidPetabIdColumn ("experiment" , EXPERIMENT_ID ),
842+ CheckValidPetabIdColumn ("experiment" , EXPERIMENT_ID , ignore_nan = True ),
830843 CheckValidPetabIdColumn ("experiment" , CONDITION_ID ),
831844 CheckExperimentConditionsExist (),
832845 CheckObservableTable (),
0 commit comments